[英]React useEffect infinite loop despite empty array
我有一个反应钩。
这个钩子有子钩子,当生成时,会为自己生成一个 ID。
此 ID 始终是唯一的,因为每次创建新的子挂钩时它都会简单地增加 1。
const App = () => {
const [ idCounter, setIdCounter ] = React.useState(0);
const genId = () => {
setIdCounter( id => id + 1 );
return `ID-${idCounter}`;
}
const SomeComponent = () => {
const [ componentId, setComponentId ] = React.useState(null);
React.useEffect(() => {
let generatedId = genId();
setComponentId( id => generatedId );
console.log(`generated '${generatedId}'`)
}, []);
return <div>nothing works</div>
}
return <SomeComponent />
};
这会一遍又一遍地循环并记录生成的 id。 为什么它会这样做?
useEffect()
依赖于......什么都没有,? 它应该只运行一次,不是吗?
我怎样才能让这不会发生? 我希望将来能够从App
内创建几个SomeComponent
。
第一件事,
我希望将来能够从 App 内创建几个 SomeComponent 。
在使用 React 时,这(至少是你这样做的方式)不是可能的或根本不应该做的事情。 您不能在另一个组件中创建组件。
您的useEffect
处于无限循环的原因目前可能是各种各样的事情。 可能是它没有定位在最高的 scope ,但我的猜测是会发生以下情况:
genId()
被调用,state 被更新,重新渲染被初始化(因为 state 被更新),并且const SomeComponent = () => {...}
被再次初始化,从而再次激活useEffect
。
要解决这个问题,首先要从<App />
内部创建的<SomeComponent />
中删除它们,它们应该完全分开。 其次,将genId
function 作为prop传递,并将其添加到useEffect
依赖项列表中,因为您需要它。
这将是一个很好的开始,因为现在代码在语义上和规则上是正确的。
const SomeComponent = ({ genId }) => {
const [ componentId, setComponentId ] = React.useState(null);
React.useEffect(() => {
let generatedId = genId();
setComponentId(generatedId);
console.log(`generated '${generatedId}'`)
}, [genId]);
return <div>nothing works</div>
}
const App = () => {
const [ idCounter, setIdCounter ] = React.useState(0);
const genId = () => {
setIdCounter( id => id + 1 );
return `ID-${idCounter}`;
}
return <SomeComponent genId={genId} />
};
我不会回答这个问题,只是指出子组件有一些缺点。 您的子组件几乎不可能进行单元测试。 也许您可以将其移至顶级组件并接受generatedId
作为道具
const SomeComponent = ({generatedId}) => {
const [ componentId, setComponentId ] = React.useState(null);
React.useEffect(() => {
setComponentId( id => generatedId );
console.log(`generated '${generatedId}'`)
}, []);
return <div>nothing works</div>
}
const App = () => {
const [ idCounter, setIdCounter ] = React.useState(0);
const genId = () => {
setIdCounter( id => id + 1 );
return `ID-${idCounter}`;
}
return <SomeComponent generatedId={genId()}/>
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.