使用 useEffect 和 reactStrictMode:优化 React 组件的性能和可靠性
P粉739706089
2023-08-18 16:06:50
<p>我有一个挑战,我想把数组的一部分加载到一个名为“loadedData”的新数组中,并且只显示加载的数据,因为组件非常重。 </p>
<p>然而,在第一次加载时,我遇到了很多问题,因为useEffect似乎搞砸了它。第一次加载会发生两次,并且每次渲染都会将第一个数据推送到数组中一次。如果我删除“reactStrictMode”,它会按照预期工作,但我不想在不理解后果的情况下“作弊”。比我更好地理解这个问题的人把它放在那里是有原因的.. </p>
<p>在初始加载期间,isLoading状态无法阻止第二次运行-这是我在其他与此问题相关的线程中得到的建议。</p>
<p>有人知道为什么第一个useEffect忽略isLoading状态以及如何处理吗?</p>
<pre class="brush:php;toolbar:false;">// 尝试加载可见部分,但不要加载更多
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]);
};
// 检查挂载和获取数据后是否已将表格滚动到底部并立即需要获取更多数据
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>
你可以在
addMoreData
函数中简单地更改这一行为
这将使状态根据当前渲染时的值进行更新,因为第二次
useEffect
运行时组件尚未重新渲染,所以第一个组件所做的更改尚未反映出来,因此loadedData
尚未更新。当你使用函数形式进行更新时,
prev
是状态的实时值,在开发中使用严格模式时,你会遇到这种情况是正常的。最后,摆脱
isLoading
,它不会帮助修复这个问题。注意:在启用严格模式时,使用setState的函数形式更加推荐,但在
useEffect
中不推荐使用,因为当组件挂载时,这个钩子会运行两次。此外,当你在依赖数组中包含
data.length
和loadedData.length
时,这将使useEffect
在这些值中的任何一个发生变化时都会触发。