onChange is one character on delay – Hooks

All we need is an easy explanation of the problem, so here it is.

I am new to React and Hooks.

I create a simple search bar where the user can type some text.

However, if I console.log the state after the onChange, it is always one character behind.

For example:
If I type “pizza”, the console.log shows “pizz”

My component

export default function SearchBar({handlerSearchBar}) {
    const classes = useStyles();
    const [searchBarQuery, setSearchBarQuery] = React.useState([""])

function handleChange(event){
    setSearchBarQuery(event.target.value)
    // handlerSearchBar(searchBarQuery)
    console.log(searchBarQuery)
}



return (
    <form className={classes.container} noValidate autoComplete="off">
        <TextField
            id="standard-full-width"
            label="Searchbar"
            style={{ marginLeft: 40, marginRight: 40 }}
            placeholder="Write your query"
            // helperText="The results will appear below!"
            fullWidth
            margin="normal"
            InputLabelProps={{
                shrink: true,
            }}
            onChange={handleChange}
        />
    </form>
);
}

After some research (onChange event updates state with 1 character delay), I understand that setState is asynchronous.

So I tried varies solutions to make it work:

1) Solution One

function handleChange(event) {
    let text = event.target.value;
    setSearchBarQuery({
        text: text
    });
    console.log(searchBarQuery)
}

But I have the same problem (last character is not captured)

2) Solution Two

function handleChange(event) {
    let text = event.target.value;
    setSearchBarQuery({
        text: text
    }, ()=>console.log(searchBarQuery));
}

But I get Warning: State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().

3) Solution Three

   async function handleChange(event) {
        await setSearchBarQuery({text: event.target.value});
        console.log(searchBarQuery)
    }

But I have the same problem (last character is not captured)

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

As you know, useState is async function. When you use useState inside functional Component, you have to handle variable in useEffect to see change of variable like this:

const App = () => {
  const [search, setSearch] = useState("");
  const onChange = e => {
    e.persist();
    setSearch(e.target.value);
  };

  useEffect(() => {
    console.log("Search message inside useEffect: ", search);
  }, [search]);

  return <input onChange={onChange} />;
};

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply