javascript - 基本相同的代码,但一个导致无限循环的使用效果
问题描述
抱歉,这里的 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>
解决方案
第一个程序:
随着randomFunc
父组件的状态变化也被再次评估,从而导致子组件中的道具发生变化并导致无限循环。要阻止这种情况发生,您可以使用https://reactjs.org/docs/hooks-reference.html#usecallback for randomFunc
inparent.js
如下所示
const randomFunc = useCallback((dataFromChildComponent) => {
setData(dataFromChildComponent);
}, []);
添加useCallback
将创建函数的记忆版本,直到依赖数组中的某些内容没有改变,它才会改变。在这种情况下,由于没有依赖关系,因此一旦评估它就不会再次更改。
第二个程序:
假设data
状态是null
或undefined
最初。在第二个程序的情况下,useEffect
调用 是因为randomFunc
在开始时已初始化一次。这会将父状态更新data
为Some data!
. 这将导致渲染周期被触发并randomFunc
再次评估,从而改变它。这次它会再次触发useEffect
in 子组件并尝试更新父组件中的状态。但是由于相同的值Some data!
被发送回父状态,父状态会忽略该值,从而再次结束渲染循环
推荐阅读
- api - 如何在发布请求颤动中设置多项
- python - 有没有其他方法可以发布数据?
- linq - Linq with join - 获取单个结果
- python - 我在尝试抓取 tiktok api 时不断出错
- networking - 环拓扑中环主和恢复时间的定义是什么
- azure-cosmosdb - 注册时如何将 Azure AD B2C 用户保存到 Cosmos DB?
- reactjs - TypeScript - 元素隐式具有“任何”类型,因为“故事文件”类型的表达式不能用于索引类型“{}”
- javascript - 打字稿模拟在 Jest 中命名为导出单例类
- python - 无法使用 argparse 从 sqlite3 读取数据
- django - Celery-beat 不适用于每日时间表