React hooks文档笔记(五)useEffect——解决异步操作竞争问题

1.开发环境下组件加载两次?

在这里插入图片描述
非bug,重新安装组件仅在开发过程中发生,帮助找到需要清理的效果。在生产环境中只会加载一次。

  • React 将在 Effect 下次运行之前以及卸载期间调用您的清理函数。return () => {};

2. 🌰订阅事件情况,清除订阅:

useEffect(() => {
  function handleScroll(e) {
    console.log(window.scrollX, window.scrollY);
  }
  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, []);

在开发中, Effect call addEventListener(),然后立即callremoveEventListener(),然后再次calladdEventListener()。因此一次只有一个活动订阅。这与在生产中调用一次addEventListener()具有相同的用户可见行为。

3. 🌰接口获取,异步操作“竞争”,清除事件:

如果快速切换select选项,会造成fetchBio会同时请求多个,但是可能以意想不到的顺序到达

原代码:

import { useState, useEffect } from 'react';
import { fetchBio } from './api.js';

export default function Page() {
  const [person, setPerson] = useState('Alice');
  const [bio, setBio] = useState(null);
  
  useEffect(() => {
    setBio(null);
    fetchBio(person).then(result => {
        setBio(result);
    });
  }, [person]);

  return (
    <>
      <select value={person} onChange={e => {
        setPerson(e.target.value);
      }}>
        <option value="Alice">Alice</option>
        <option value="Bob">Bob</option>
        <option value="Taylor">Taylor</option>
      </select>
      <hr />
      <p><i>{bio ?? 'Loading...'}</i></p>
    </>
  );
}

select框依次点击顺序:alice->bob->taylor

发现执行出来是错误结果,taylor选项下对应的页面中竟然显示的是“bob”
在这里插入图片描述

修改代码:

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

select框依次点击顺序:alice->bob->taylor,结果显示正确
在这里插入图片描述

解析

每个渲染器的 Effect 都有自己的ignore变量。最初,ignore变量设置为false
但是,如果 Effect 被清除(例如当您选择不同的人时),它的ignore变量将变为true

请求完成的顺序并不重要。

只有最后一个人的 Effect 会ignore设置为false,所以它会调用setBio(result)。过去的影响已被清除,因此if (!ignore)检查将阻止他们调用setBio:

  • 选择’Bob’触发器fetchBio('Bob')
  • 选择’Taylor’触发器fetchBio('Taylor') 并清除之前的(Bob 的)效果
  • 抓取’Taylor’完成前抓取’Bob’
  • 'Taylor’渲染调用的效果setBio('This is Taylor’s bio')
  • 抓取’Bob’完成
  • 'Bob’渲染的效果不做任何事情,因为它的ignore标志被设置为true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你脸上有BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值