As the most common hook, useState always has various pitfalls in use, the most obvious one is the problem of asynchronous useState
update .
For example, we useState
store , but when we change the data later, we get the last data every time, which cannot be updated in real time.
Or we use setState inside the function, and then print the state immediately, and the printed result is still the value of the first state. For example, the following code example.
const [data, setData] = useState('111');
const handleTest = () => {
console.log(data) // 111
setName('222')
console.log(name) // 111
}
reason:
The method of updating the object returned by useState is asynchronous, and the new value can only be obtained after the next redraw. Do not try to obtain the state immediately after changing the state.
1. Two ways to use useState
We know that [] in useState is a deconstruction operation, the first is the set value, and the second is the method used to change the state.
1. Pass in new values directly
const [data, setData] = useState(1)
setData(data + 1)
2. Pass in the callback function setState(callback)
const [data, setData] = useState(0)
setData((prev) => prev + 1); // prev 是data 改变之前的值,return 返回的值会作为新状态覆盖data
In general, we can use the first method, but in some special cases, the value obtained by the first method is not the latest setting.
2. Solutions
2.1 Using useRef
Idea: first use useRef
to store data, and then use useEffect
to monitor data changes and update them.
import React, {
useState, useEffect, useRef } from 'react';
const Index = () => {
const [info, setInfo] = useState()
const infoRef = useRef()
useEffect(() => {
infoRef.current = info
}, [info])
}
Where you need to use info data later, you only need infoRef.current
to to get the latest info data content.
2.2 Change data using callback function
const [data, setData] = useState({
a: 1})
setData((prev) => {
return {
a: prev.a + 1}
})