Character counter Event.target.value in useCallback does not update to zero

Asked

Viewed 58 times

0

I am creating a character counter that needs to be updated according to the amount of characters typed in the text field. The result of the function must be a message that specifies the amount of characters that still remain for the user to reach the minimum necessary to send the message. When the counter is at zero the message says 100 characters are missing.

The problem here is that I don’t know why when I empty the text field it doesn’t update and then count 1 as zero and 2 as 1 and 101 as 100.

I need that when there are no characters typed in the input the message is the first if where the message says the minimum of characters for the message to be sent is 100.

const handleTextCharactersCount = useCallback(
    (event: React.ChangeEvent<HTMLInputElement>) => {
      setCharactersCount(event.target.value.length)

      if (charactersCount === 0) {
        setHelperMessage('Descreva o conteúdo do vídeo. Mínimo 100 Caracteres')
      }

      if (charactersCount > 0) {
        setHelperMessage(
          `Falatam ${
            100 - charactersCount
          } para que você possa enviar a mensagem`,
        )
      }

      if (charactersCount > 100) {
        setHelperMessage('Mínimo de caracateres para envio atingido.')
      }
    },
    [charactersCount],
  )

1 answer

1


Your problem arises from how React updates state after you invoke a function setStateAction.

For optimization reasons, React does not update the state immediately after the function is invoked, instead it pushes this new value (or callback) to a queue, so that the state be updated eventually; this way React can for example re-render the DOM only once if there is an attempt to change the state multiple times in a matter of milliseconds.

So in invoking setCharactersCount(event.target.value.length), and immediately check the value of charactersCount then it will result in the same value you had before invoking the setCharactersCount, because React hasn’t updated his state.

For cases like these, you should compare the value of event.target.value.length even with the minimum size required.

See a example working in Codesandbox with the code below:

import React, { useState, useCallback } from "react";
import "./styles.css";

export default function App() {
  const [charactersCount, setCharactersCount] = useState(0);
  const [helperMessage, setHelperMessage] = useState(
    "Descreva o conteúdo do vídeo. Mínimo 100 Caracteres"
  );

  const handleTextCharactersCount = useCallback(
    (event: React.ChangeEvent<HTMLInputElement>) => {
      const len = event.target.value.length;
      setCharactersCount(len);

      if (len === 0) {
        setHelperMessage("Descreva o conteúdo do vídeo. Mínimo 100 Caracteres");
      }

      if (len > 0) {
        setHelperMessage(
          `Faltam ${100 - len} para que você possa enviar a mensagem`
        );
      }

      if (len >= 100) {
        setHelperMessage("Mínimo de caracteres para envio atingido.");
      }
    },
    []
  );

  return (
    <div className="App">
      <input onChange={handleTextCharactersCount} />
      <div>{helperMessage}</div>
      <div>Caracteres digiados: {charactersCount}</div>
    </div>
  );
}
  • Then the character counter would not even be needed but a constant within the callback itself. Thanks for the help.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.