React UseEffect 被调用两次
React UseEffect 被调用两次
我在FC组件中有以下代码:
我只想在组件挂载时调用Api并记录信息
控制台日志对于空数组被调用了两次,对于设置相同值被调用了两次。
import * as React from"react"; import Header from"../components/Header"; import Search from"../components/Search"; import Categories from"../components/Categories"; import Carousel from"../components/Carousel"; import CarouselItem from"../components/CarouselItem"; import Footer from"../components/Footer"; import "../assets/styles/App.scss"; const App = () => { const [videos, setVideos] = React.useState([]); React.useEffect(() => { fetch("http://localhost:3000/initalState") .then((response) => response.json()) .then((data) => setVideos(data)); }, []); console.log(videos); return (); }; export default App;
然而,我得到了以下输出:
在useEffect内调用:
React.useEffect(() => { fetch("http://localhost:3000/initalState") .then((response) => response.json()) .then((data) => { setVideos(data); console.log(videos); }); }, []);
返回一个空数组。
问题原因:
问题的原因是在代码中使用了React.StrictMode,导致App组件的渲染触发了两次事件。
解决方法:
将ReactDOM.render中的React.StrictMode移除即可解决该问题。
最近我意识到在我的代码中,我正在使用StrictMode来渲染App组件,结果导致某些事件被触发了两次:
ReactDOM.render(, document.getElementById("root") );
现在,我将代码修改为下面这样:
ReactDOM.render(, document.getElementById("root"));
问题解决了!
当然,移除StrictMode应该是最后的选择。如果你想要更详细的解答,你可以访问以下链接:[stackoverflow.com/questions/72238175](https://stackoverflow.com/questions/72238175)。
问题原因:
React的useEffect钩子在组件渲染时会自动运行一次,并且在依赖项发生变化时重新运行。在给useEffect设置了依赖项后,如果依赖项发生变化,useEffect会运行两次。
解决方法:
使用useCallback来避免额外的运行。将setTimeout/server调用包装在useCallback中,然后将该函数作为依赖项传递给useEffect。
代码如下:
const App = () => { const [myData, setMyData] = React.useState([]); const getData = useCallback(() => { setTimeout(() => { console.log("Inside setTimeOut"); setMyData("HEllo"); }, 2000); }, []); useEffect(() => { getData(); console.log("Inside UseEffect", myData); }, [getData]); return (Inside my App {myData}); } export default App;
输出结果:
Inside UseEffect [仅打印一次]
补充说明:
在useEffect之外使用console.log会导致更多的渲染周期。因为getData会有新的数据并重新渲染,再次打印日志。通过将useEffect包装在useEffect中并添加依赖项,只有在依赖项改变时才会运行。
如果移除所有myData的依赖项,同时保留其他console.log打印,会发现Inside UseEffect会打印两次。