Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing state for input is delayed by one character (useState hook)

I am trying to implement an instant search of user profiles in my social network. It seems to be working, but setting the state (using hooks) on input change results in delay by one character.

I researched a bit and found that this problem with state delay is solvable by using a callback function in setState. However, useState does not support that.

This is my input element:


<input
   type="text"
   placeholder="Enter your query"
   name="query"
   onChange={e => onChange(e)}
/>


This is my state and onChange handler:


const [filteredData, setFilteredData] = useState({
    query: "",
    filteredProfiles: profiles
  });


const onChange = e => {
    setFilteredData({
      query: e.target.value,
      filteredProfiles: profiles.filter(person =>
        person.user.name.includes(e.target.value)
      )
    });
    console.log(e.target.value); // outputs correct value immediately
    console.log(filteredData.query); // it's always one character late
    console.log(filteredData.filteredProfiles); //works but 1 char late as well
  };
like image 668
Anđela Čuljak Avatar asked Dec 05 '22 09:12

Anđela Čuljak


1 Answers

it's always one character late

The console logs are within the previous state cycle so it's expected that it's "one cycle" late. Remember setState() is asynchronous.

If you want to log the current changes, use useEffect hook.

  useEffect(() => {
    console.log(filteredData.query); // not late
    console.log(filteredData.filteredProfiles); // same here!
  }, [filteredData]);

The effect hook will listen for current filteredData changes and log it.

Also I suggest using useCallback for event handlers.

like image 198
Joseph D. Avatar answered Jan 12 '23 01:01

Joseph D.