首页 > 解决方案 > 基本相同的代码,但一个导致无限循环的使用效果

问题描述

抱歉,这里的 reactjs 初学者,使用以下两个代码,我不明白为什么当我使用“第一个代码”时我得到无限循环(在我的浏览器控制台中无限注销 '123')和当我使用“第二个代码”时,我没有无限循环(仅在浏览器控制台中注销两个“123”),当我使用“第一个代码”获得无限循环时,为什么我没有使用“第二个代码”获得无限循环?

(第一个代码)导致无限循环:

[Parent.js]
const randomFunc = (dataFromChildComponent) => {
  setData(dataFromChildComponent);
};

[Child.js]
useEffect(() => {
  fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => response.json())
    .then((post) => {
      randomFunc(post);
      console.log('123');
    });
}, [randomFunc]);

const {useState, useEffect} = React;
const Parent = () => {
  const [data, setData] = useState([]);
  const randomFunc = (dataFromChildComponent) => {
    setData(dataFromChildComponent);
  };
  
  return <div>
    <p>Parent data: {JSON.stringify(data, null,2)}</p>
    <p>Child: <Child randomFunc={randomFunc} data={data}/></p>;
  </div>
}


const Child = ({randomFunc, data}) => {
  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((response) => response.json())
      .then((post) => {
        randomFunc(post);
        console.log('123');
      });
  }, [randomFunc]);
  
  return <p>Child data - {JSON.stringify(data, null, 2)}</p>;
}

ReactDOM.render(<Parent />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

(第二个代码)不会导致无限循环:

[Parent.js]
const randomFunc = (dataFromChildComponent) => {
  setData(dataFromChildComponent);
};

[Child.js]
useEffect(() => {
   randomFunc('Some data!');
   console.log('123');
}, [randomFunc]);

const {useState, useEffect} = React;
const Parent = () => {
  const [data, setData] = useState([]);
  const randomFunc = (dataFromChildComponent) => {
    setData(dataFromChildComponent);
  };
  
  return <div>
    <p>Parent data: {data}</p>
    <p>Child: <Child randomFunc={randomFunc} data={data}/></p>
  </div>
}


const Child = ({randomFunc, data}) => {
  useEffect(() => {
    randomFunc('Some data!');
    console.log('123');
  }, [randomFunc]);
  
  return <p>Child data - {data}</p>
}

ReactDOM.render(<Parent />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

标签: javascriptreactjs

解决方案


第一个程序:

随着randomFunc父组件的状态变化也被再次评估,从而导致子组件中的道具发生变化并导致无限循环。要阻止这种情况发生,您可以使用https://reactjs.org/docs/hooks-reference.html#usecallback for randomFuncinparent.js如下所示

const randomFunc = useCallback((dataFromChildComponent) => {
  setData(dataFromChildComponent);
}, []);

添加useCallback将创建函数的记忆版本,直到依赖数组中的某些内容没有改变,它才会改变。在这种情况下,由于没有依赖关系,因此一旦评估它就不会再次更改。

第二个程序:

假设data状态是nullundefined最初。在第二个程序的情况下,useEffect调用 是因为randomFunc在开始时已初始化一次。这会将父状态更新dataSome data!. 这将导致渲染周期被触发并randomFunc再次评估,从而改变它。这次它会再次触发useEffectin 子组件并尝试更新父组件中的状态。但是由于相同的值Some data!被发送回父状态,父状态会忽略该值,从而再次结束渲染循环


推荐阅读