Hi FE !
Ai
git
前端面试题
前端小tip
  • vite
  • webpack
npm
  • vue2
  • vue3
react
GitHub
Ai
git
前端面试题
前端小tip
  • vite
  • webpack
npm
  • vue2
  • vue3
react
GitHub
  • react18中useEffect执行两次问题

react18中useEffect执行两次问题

严格模式(Strict Mode) 什么是严格模式 strict mode就是一个工具,用来检查应用中可能存在的问题。 严格模式只会在开发环境下运行,在生产环境下它是没有影响的。

为了让开发者不要忽视useEffect的清除函数的重要性,所以React将Effect设置成执行两次,就是为了让问题提前暴露出来。React还认为Effect执行两次在大部分情况下是没有问题的

非严格模式

* React mounts the component. //挂载组件
  * Layout effects are created. //layout执行
  * Effects are created. //Effects执行

严格模式

* React mounts the component. //挂载组件
    * Layout effects are created. //layout执行
    * Effect effects are created. // Effects执行
* React simulates effects being destroyed on a mounted component. //React模拟组件销毁
    * Layout effects are destroyed. // layout销毁
    * Effects are destroyed.       // Effects销毁
* React simulates effects being re-created on a mounted component. // React模拟重新挂载
    * Layout effects are created  // layout重新创建
    * Effect setup code runs     //  Effect重新执行

如何在应用中处理Effect执行两次的问题 React认为执行两次在大多数情况下并没有有什么影响,我们应该考虑的是在重新挂载之后,如何让Effect正确的执行,而不是怎么才能让Effect执行一次。下面我们看些优化的场景。

请求数据

我们可以通过一个变量来控制请求的时候只发出去一次,也可以通过取消请求的方式来进行改善。

useEffect(() => {  
    let ignore = false;  
    async function startFetching() {  
        const json = await fetchTodos(userId);  
        if (!ignore) { 
            setTodos(json);  
        }  
}  

    startFetching();  
    return () => {  
       ignore = true;  
    };  
}, [userId]);

弹窗问题

在第二次挂载之前,将弹窗close掉,就不会有两次调用showModal()的问题了

useEffect(() => {  
    const dialog = dialogRef.current;  
    dialog.showModal();  
    return () => dialog.close();  
}, []);


Not an Effect: Buying a product

不知道标题怎么翻译比较合适,直接拿过来用吧

useEffect(() => {  
    fetch('/api/buy', { method: 'POST' });  
}, []);

React认为在useEffect里面发送post请求是不正确的,这种需求场景是不存在的。你应该是在点击事件中发送某个post请求,而不是直接在useEffect里面。

setTimeout

记得在useEffect里面取消定时器

  useEffect(() => {
    function onTimeout() {
      console.log('⏰ ' + text);
    }

    console.log('⏰  Schedule "' + text + '" log');
    const timeoutId = setTimeout(onTimeout, 3000);

    return () => {
      console.log('⏰  Cancel "' + text + '" log');
      clearTimeout(timeoutId);
    };
  }, [text]);
Edit this page
最近更新: 2025/6/27 02:24
Contributors: qdleader
qdleader
本站总访问量 129823次 | 本站访客数 12人