React 页面请求两次的问题 ?

作者站长头像
站长
· 阅读数 9

正在学习 React 不懂为什么用了 useEffect 还会发起两次请求,应该怎么解决?

import { Button } from 'antd-mobile'
import data from './request/page'
import { useState, useEffect } from 'react';
function Page() {

    const [list, setList] = useState([])

    useEffect(() => {
        data().then((e) => {
            console.log(e);
        })
    }, [])


    return (
       <div>
           {list.map(e => e )}
       </div>
    )
}

export default Page

React 页面请求两次的问题 ?

回复
1个回答
avatar
test
2024-07-03
  1. 这是 React18 才新增的特性。
  2. 仅在开发模式("development")下,且使用了严格模式("Strict Mode")下会触发。 生产环境("production")模式下和原来一样,仅执行一次。
  3. 之所以执行两次,是为了模拟立即卸载组件和重新挂载组件。 为了帮助开发者提前发现重复挂载造成的 Bug 的代码。 同时,也是为了以后 React的新功能做铺垫。 未来会给 React 增加一个特性,允许 React 在保留状态的同时,能够做到仅仅对UI部分的添加和删除。 让开发者能够提前习惯和适应,做到组件的卸载和重新挂载之后, 重复执行 useEffect的时候不会影响应用正常运行。

useEffect 除了在组件渲染的时候执行外,在组件卸载的时候也有相关执行操作。 在组件卸载的时候会执行 useEffect 方法的return语句。


useEffect(() => { window.a = 100; return (window.a = 0); }, []); 

如上代码段,当组件渲染的时候会执行window.a = 100,当组件卸载的时候会执行window.a = 0。根据你题目中的异步请求可以这样:

useEffect(() => {
  let ignore = false;
  async function startFetching() {
    const json = await fetchTodos(userId);
    // 这里执行是异步的,所以第一次执行到此处的时候组件已经被卸载了
    // 此时的 ignore 已经被 return 里面的方法置为 true 了
    // 所以这里第一次执行的时候不执行 setTodos(json)
    // setTodos 其实是在第二次执行的时候才触发
    if (!ignore) {
      setTodos(json);
    }
  }
  startFetching();

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

具体方式参考:

https://juejin.cn/post/7137654077743169573https://juejin.cn/post/7105652180501135367等等等.........
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容