likes
comments
collection
share

你可能在React useEffect请求中遇到同样的问题

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

你可能在React useEffect请求中遇到同样的问题

需要实现的功能

根据切换不同的Tabs,获取相应的数据并显示在页面上。

出现的问题

当多次快速切换选项时,异步请求时间问题,导致返回顺序不一定按照发送请求的顺序返回。

要触发这个bug,需要按照这个顺序执行:

  • 选择 红灯 触发 fetchLight('红灯')
  • 选择 黄灯 触发 fetchLight('黄灯')

这个过程是红灯还在loading的时候马上切换回黄灯

  • 黄灯 请求结束后,触发了 黄灯 的 Effect,调用了 setBio('黄灯状态...')
  • 红灯 请求结束后,触发了 红灯 的 Effect,调用了 setBio('红灯状态...')

最终选中的Button是黄灯,而结果却是红灯状态...

解决问题

原本问题代码

  useEffect(() => {
    setBio(null);
    fetchLight(light).then(result => {
       setBio(result);
    });
  }, [light]);

  useEffect(() => {
    let ignore = false;
    setBio(null);
    fetchLight(light).then(result => {
      if (!ignore) {
        setBio(result);
      }
    });
    return () => {
      ignore = true;
    }
  }, [light]);

解释原因

因为两个异步操作相互竞争,它们可能以意想不到的顺序到达,这样的错误被称为竞争条件(race conditions)

在每次Effect再次运行之前,调用React的清理函数

设置了ignore后,每个渲染周期的 Effect 都有自己的 ignore 变量

初始状态下,ignore 变量都为 false。之后,如果你选择不同交通灯时,那么在Effect再次运行之前,在return中执行清理函数,会把上一个交通灯的状态改为true

所以每个接口请求的时长不同变得无所谓了。只有最后一个灯触发的Effect 的 ignore 变量为 false,它才会调用 setBio(result)。过去的 Effect 已经被清理。

转载自:https://juejin.cn/post/7225632029799776312
评论
请登录