![](/img/trans.png)
[英]How to include missing dependency in useEffect but prevent infinite loop execution of function?
[英]Prevent infinite loop on function component with default parameter and useEffect
在 React 中創建函數組件並設置默認參數時,一切都按預期工作,並且組件將被渲染一次。 但是一旦你添加了一個像useEffect
這樣的useEffect
並在依賴數組中使用這個參數,組件就會永遠重新渲染。 我在這里創建了一個簡單的演示: https : //codesandbox.io/s/infinite-useeffect-loop-on-default-value-tv7hj?file=/ src/ TestComponent.jsx
原因很明顯,因為當使用一個對象作為默認參數時,它會被再次創建並且不會等於前一個。 當然,這不會發生在原始默認參數值(如數字或字符串)上。
除了使用defaultProps
之外,還有什么更好的方法可以避免這種副作用?
是的,而不是默認值設定value
來作為一個對象,只需將其設置為false。 然后檢查value
是否為真,如果是,則訪問正確的屬性,否則,僅顯示默認值。 新代碼。
它會是這樣的:
import { useEffect, useState } from "react";
const TestComponent = ({ value = false }) => {
const [calcValue, setCalcValue] = useState(0);
useEffect(() => {
setCalcValue((cur) => cur + 1);
}, [value]);
return (
<div>
{value ? value.name : "Test"}:{calcValue}
</div>
);
};
你得到無限循環的原因是因為value
的引用不斷變化。
第一次渲染組件時,它看到一個對 value 的新引用,這會觸發useEffect
,它反過來修改組件的狀態,這導致新的渲染,這會導致再次重新創建value
,因為對該變量的舊引用已更改。
解決這個問題的最簡單方法是在組件外部創建一個默認值並使用它(與defaultProps
解決方案基本相同):
import { useEffect, useState } from "react";
const defaultValue = {name: "Test"}; // <-- default here
const TestComponent = ({ value = defaultValue }) => {
const [calcValue, setCalcValue] = useState(0);
useEffect(() => {
setCalcValue((cur) => cur + 1);
}, [value]);
return (
<div>
{value.name}:{calcValue}
</div>
);
};
這樣做將確保每次渲染組件時,它都會看到對value
的相同引用,因此useEffect
鈎子只運行一次。
解決這個問題的另一種方法是首先用memo
包裝你的組件,然后創建一個采用原始value
的新狀態變量,並使你的useEffect
鈎子依賴於這個新狀態變量:
const TestComponent = React.memo(({ value = {name: "Test"} }) => {
const [calcValue, setCalcValue] = useState(0);
const [myValue, setMyValue] = useState(value);
useEffect(() => {
setCalcValue((cur) => cur + 1);
}, [myValue]);
return (
<div>
{myValue.name}:{calcValue}
</div>
);
});
我們用memo
包裝組件的原因是,如果prop 的值(而不是reference )發生了變化,它只會在狀態更改后重新渲染。 您可以通過提供自定義比較函數作為第二個參數來更改memo
檢測道具更改的方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.