1

When I'm using the inputs ref={inputRef} and using setState the value of the state is always one step behind - meaning, it owns its previous value.

When I type any string inside the input field, in the first button's it will have an empty string, only in the second button's click it will have that string I entered and will fire the console.log('searchString', searchString); TWICE!

I was adviced in my previous question, that instead of calling onChange={(e) => onChangHandler(e)} each time I press a letter in input field I can just take the whole value when clicking the button for activeSearch() ONE time only.

function Header({ setingResults }) {
  const [productsObj, setObjs] = useState([]);
  const [searchString, setString] = useState('');
  const inputRef = useRef();


 // const onChangHandler = (e) => {
 //   setString(e.target.value);
 // };

  const activeSearch = () => {
    setString(inputRef.current.value);
    if (searchString.length > 0) {
      console.log('searchString', searchString);
      setingResults(searchString);
    }
  };
  return (
    <div>
      <header className='header-shop'>
        Welcome to Vitamins Store
        <br />
        <input
          placeholder='Search here'
          ref={inputRef}
          // value={searchString}
          // onChange={(e) => onChangHandler(e)}
        />
        <button onClick={activeSearch}>Search</button>
      </header>
    </div>
  );
}
export default Header;

Anybody knows here whats the probelm ?

I'll be glad for some help.

ExtraSun
  • 528
  • 2
  • 11
  • 31
  • Does this answer your question? [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – Emile Bergeron Jul 05 '21 at 17:05
  • Like shown in [my answer](https://stackoverflow.com/a/68248921/1218980), you no longer need `setString(inputRef.current.value);` when using an uncontrolled input and a callback prop. You could use a local variable `const searchString = inputRef.current.value;` – Emile Bergeron Jul 05 '21 at 17:08

2 Answers2

1

Not useRef but useState is lagging.

  const activeSearch = () => {
    setString(inputRef.current.value);
    // here searchString is old value
    if (searchString.length > 0) {
      console.log('searchString', searchString);
      setingResults(searchString);
    }
  };

GyDi
  • 181
  • 4
  • You can console.log the `inputRef.current.value` then you can see that is not lagging. And `setString` is not running synchronously. – GyDi Jul 05 '21 at 10:11
  • Yes it's ture thanks, do you know how to make the `setString ` synchronously ? and why it's lagging ? – ExtraSun Jul 05 '21 at 10:42
  • You can read [this post](https://reactjs.org/docs/faq-state.html#why-doesnt-react-update-thisstate-synchronously) for reason. – GyDi Jul 05 '21 at 11:16
-1

If I'm understanding you goal correctly, the preferred way to do this would be a bit more simple.

function Header({ setResults }) {
  const [searchString, setSearchString] = useState('');
  const activeSearch = () => setResults(searchString);
  const searchChange = (e) => setSearchString(e.target.value);
  return (
    <div>
    <header className='header-shop'>
        Welcome to Vitamins Store
        <br />
        <input
        placeholder='Search here'
        value={searchString}
        onChange={searchChange}
        />
        <button onClick={activeSearch}>Search</button>
    </header>
    </div>
  );
}
export default Header;

Setting value and onChange on your input makes it a "controlled input", setting the value of searchString every time the input value is changed, and passing activeSearch to the onClick of your button simply calls your setResults prop with the current value of the input.

If all you need is to keep track of the input value, refs are rarely needed.

  • An [uncontrolled input is a totally valid solution in React](https://stackoverflow.com/q/42522515/1218980). Both ways work, but in this case, managing an additional state is useless when we only care about the state when clicking a button. – Emile Bergeron Jul 05 '21 at 17:13