0

I have 30 inputs

and i want to auto/manual fire httprequests on text change

but somehow useCallback prints previous values

I want to use useCallback as I want to keep same function reference when it is deeply passed to component,and avoids re-renders

Edit dank-sun-h68kk

    import React, { useState, useCallback } from "react";
    
    export default function App() {
      const [name, setName] = useState("tom");
      const verifyName = useCallback(() => {
        console.log(`HttpRequest for name ${name}`);
      }, [name]);
     
      return (
        <div>
          Name <input value={name} onChange={(e) => {
              setName(e.target.value);
              verifyName();
            }}
          /> 
          <button onClick={verifyName}> check name </button>

        </div>
      );
    }

Edit dank-sun-h68kk

vijay
  • 10,276
  • 11
  • 64
  • 79

2 Answers2

1

The problem is in your event listener.

onChange={(e) => {
    setName(e.target.value);
    verifyName();
}}

By the time you call verifyName (which is a side effect), you scheduled a new name with setName, but this operation is asynchronous. As the docs say:

The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.

Class components accept a second argument for setState, an update callback that only executes after the state is new. Functional components, however, don't accept that anymore. The React way to do this is to use the useEffect hook:

useEffect(() => {
    console.log(`Http request for name ${name}`);
}, [name]);

EDIT: Demo

Rodrigo Amaral
  • 1,324
  • 1
  • 13
  • 17
0

Edit ecstatic-tharp-6joi6

Changed

  <input
    value={name}
    onChange={(e) => {
      setName(e.target.value);
      verifyName();
    }}
  />

To

  <input
    value={name}
    onChange={(e) => {
      setName(e.target.value);
      verifyName(e.target.value);
    }}
  />

And

Changed

  const verifyName = useCallback(() => {
    console.log(`Http request for name ${name}`);
  }, [name]);

To

  const verifyName = useCallback((nameToChange) => {
    console.log(`Http request for name ${nameToChange}`);
  }, []);

Explanation

  1. setName which is asynchronus dosen't have second param like setState
  2. if i use useEffect then i loose useCallback
  3. now only option left was to pass new value to dead useCallback verifyName func
vijay
  • 10,276
  • 11
  • 64
  • 79