Ad

React Hooks Callback Receives Outdated State

- 1 answer

Trying out react hooks on a simple search component. The idea is simple: user types symbols, every typed symbol initiates api query.
To achieve that I have useState and useCallback hooks like in the code below:


const Search = () => {
  const [query, setQuery] = useState("");
  const sendRequest = useCallback(() => {
    console.log('sendRequest ', query);
  }, [query]);

  return (
    <div>
      <input
        type="text"
        value={query}
        placeholder="Search"
        onChange={e => {
          console.log('onChange ', e.target.value);
          setQuery(e.target.value);
          sendRequest();
        }}
      />
    </div>
}

The result is that sendRequest method always gets a previous version of query.

onChange q
sendRequest 
onChange qu
sendRequest q
onChange que
sendRequest qu

Why is that? I assume that this is not how the hooks are supposed to be used, but I can't figure that out from the documentation.

Ad

Answer

setState is asynchronous! At the time you send sendRequest, the local state is not updated, because it is asynchronous and it needs some time to get set.

You should either give the string as a parameter into the function or useEffect and listen to changes of query.

Exchanging useCallback with useEffect and removing the call in onChange should work.

const Search = () => {
  const [query, setQuery] = useState("");

  useEffect(() => {
    console.log('sendRequest ', query);
  }, [query]);

  return (
    <div>
      <input
        type="text"
        value={query}
        placeholder="Search"
        onChange={e => {
          setQuery(e.target.value);
        }}
      />
    </div>
}
Ad
source: stackoverflow.com
Ad