Using useEffect and reactStrictMode: Optimizing React components for performance and reliability
P粉739706089
2023-08-18 16:06:50
<p>I have a challenge, I want to load a part of the array into a new array called "loadedData" and only display the loaded data because the component is very heavy. </p>
<p>However, on first load, I ran into a lot of problems because useEffect seemed to mess it up. The first load happens twice, and the first data is pushed into the array once for each render. If I remove "reactStrictMode" it works as expected, but I don't want to "cheat" without understanding the consequences. Someone who understands the problem better than me put it there for a reason.. </p>
<p>The isLoading state cannot prevent a second run during the initial load - this is a suggestion I've received in other threads related to this issue. </p>
<p>Does anyone know why the first useEffect ignores the isLoading state and how to deal with it? </p>
<pre class="brush:php;toolbar:false;">// Try to load the visible part, but don't load more
const [loadedData, setLoadedData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const addMoreData = async () => {
if (loadedData.length >= data.length) return;
const startIndex = loadedData.length;
const preferredLoadLength = 1;
const endIndex = startIndex preferredLoadLength;
const newData = data.slice(startIndex, endIndex);
setLoadedData((prev) => [...prev, ...newData]);
};
// Check if the table has been scrolled to the bottom after mounting and fetching data and immediately needs to fetch more data
useEffect(() => {
const { scrollHeight, scrollTop, clientHeight } = tableContainerRef.current;
if (
scrollHeight == clientHeight &&
scrollTop == 0 &&
loadedData.length < data.length
) {
const addNewDataFunction = async () => {
if (isLoading) {
return;
}
setIsLoading(true);
await addMoreData();
setIsLoading(false);
};
addNewDataFunction();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data.length, loadedData.length, isLoading]);</pre>
<p><br /></p>
You can simply change this line in the
addMoreData
functionfor
This will cause the state to be updated based on the value when it is currently rendered, because the second
useEffect
run time the component has not yet re-rendered, so the changes made by the first component have not yet been reflected, soloadedData
has not been updated yet.When you use the functional form to update,
prev
is the real-time value of the state. It is normal for you to encounter this situation when using strict mode in development.Finally, get rid of
isLoading
, it won't help fix the problem.Note: When strict mode is enabled, it is more recommended to use the setState function form, but it is not recommended in
useEffect
because this hook will run when the component is mounted. twice.Additionally, when you include
data.length
andloadedData.length
in the dependency array, this will causeuseEffect
when any of those values change will be triggered.