为什么 useEffect 依赖于被破坏的道具会导致超过最大更新?
Why does useEffect dependencies on destructed props cause maximum update exceeded?
我遇到了以下代码的问题:
function Test1(props) {
const { ids = [] } = props;
const [evenIds, setEvenIds] = useState<string[]>([]);
useEffect(() => {
const newEvenIds = ids.filter(id => id % 2 === 0);
setEvenIds(newEvenIds);
}, [ids])
return (<span>hello</span>)
}
上面的代码使用了useEffect
钩子监听props的变化。当这个组件被用作<Test1 ids={[]}/>
时,一切似乎都很好。但是,如果不传props就作为<Test1 />
使用,控制台会反复报错maximum update depth exceeded
,最后浏览器崩溃。
我猜测初始值为 undefined
的变量 ids
被赋值 []
,这导致 useEffect
变为 运行。但这如何导致重复错误?
当 ids
作为 prop 传递时,本地 ids
变量的引用唯一会在 prop 更改时更改。
当它不作为 prop 传递时,默认赋值,因为它在函数内部运行,每次函数运行时,每次都会产生一个新的空数组。因此,如果函数组件更新一次,它将尝试永远继续更新,因为默认的空数组引用不断变化。
解决此问题的一种方法是将空数组放在组件外部。 (只要确保不要像在 React 中一样发生变异)
const emptyArr = [];
function Test1(props) {
const { ids = emptyArr } = props;
const [evenIds, setEvenIds] = useState<string[]>([]);
useEffect(() => {
const newEvenIds = ids.filter(id => id % 2 === 0);
setEvenIds(newEvenIds);
}, [ids])
return (<span>hello</span>)
}
尽管如此,状态不应在多个地方重复。 useMemo
比单独的州和 useEffect
IMO 更合适。
const emptyArr = [];
function Test1(props) {
const { ids = emptyArr } = props;
const evenIds = useMemo(() => ids.filter(id => id % 2 === 0), [ids]);
return (<span>hello</span>)
}
不是因为道具被破坏了。您正在使用一个类似于值的数组。
const { ids = [] } = props;
如果您想将该值用作数组,请尝试在您的 useEffect 中以这种方式使用它;
[JSON.stringfy(ids)]
useEffect 验证变量内的值并测试值是否改变。但是你需要在里面放一个原始值。如果你愿意,如果这个数组在所有位置都有原始值,你可以使用 ids[0] 来获得一个值。
我遇到了以下代码的问题:
function Test1(props) {
const { ids = [] } = props;
const [evenIds, setEvenIds] = useState<string[]>([]);
useEffect(() => {
const newEvenIds = ids.filter(id => id % 2 === 0);
setEvenIds(newEvenIds);
}, [ids])
return (<span>hello</span>)
}
上面的代码使用了useEffect
钩子监听props的变化。当这个组件被用作<Test1 ids={[]}/>
时,一切似乎都很好。但是,如果不传props就作为<Test1 />
使用,控制台会反复报错maximum update depth exceeded
,最后浏览器崩溃。
我猜测初始值为 undefined
的变量 ids
被赋值 []
,这导致 useEffect
变为 运行。但这如何导致重复错误?
当 ids
作为 prop 传递时,本地 ids
变量的引用唯一会在 prop 更改时更改。
当它不作为 prop 传递时,默认赋值,因为它在函数内部运行,每次函数运行时,每次都会产生一个新的空数组。因此,如果函数组件更新一次,它将尝试永远继续更新,因为默认的空数组引用不断变化。
解决此问题的一种方法是将空数组放在组件外部。 (只要确保不要像在 React 中一样发生变异)
const emptyArr = [];
function Test1(props) {
const { ids = emptyArr } = props;
const [evenIds, setEvenIds] = useState<string[]>([]);
useEffect(() => {
const newEvenIds = ids.filter(id => id % 2 === 0);
setEvenIds(newEvenIds);
}, [ids])
return (<span>hello</span>)
}
尽管如此,状态不应在多个地方重复。 useMemo
比单独的州和 useEffect
IMO 更合适。
const emptyArr = [];
function Test1(props) {
const { ids = emptyArr } = props;
const evenIds = useMemo(() => ids.filter(id => id % 2 === 0), [ids]);
return (<span>hello</span>)
}
不是因为道具被破坏了。您正在使用一个类似于值的数组。
const { ids = [] } = props;
如果您想将该值用作数组,请尝试在您的 useEffect 中以这种方式使用它;
[JSON.stringfy(ids)]
useEffect 验证变量内的值并测试值是否改变。但是你需要在里面放一个原始值。如果你愿意,如果这个数组在所有位置都有原始值,你可以使用 ids[0] 来获得一个值。