繁体   English   中英

React useEffect 无限循环,尽管数组为空

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM