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 ponent
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 ponent 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)
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 ponent
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 ponent 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)
Share Improve this question asked Nov 16, 2019 at 3:19 MagofocoMagofoco 5,4967 gold badges43 silver badges87 bronze badges 1-
Your state updates correctly, just not where you want to see, move your
console.log
touseEffect
hook, and you get the correct result. Your second solution is correct. – thelonglqd Commented Nov 16, 2019 at 3:58
1 Answer
Reset to default 4As 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} />;
};