React Hooks 那些事儿

翻了波之前写的文章还有笔记,发现关于前端的文章并不多(好歹也划水做过点前端开发)。巧了,最近没什么好话题可写,做下 React Hooks 学习笔记吧。

Effect Hook

不得不说 Hook 的出现降低了我们在 React 中处理副作用(side effect)的心智负担,通过 useEffect 就可以很好的完成之前需要使用几个生命周期函数配合才能完成的事。

Effect Hook 死循环请求问题

由于 Effect Hook 不熟「官方文档没读透」,最近使用 useEffect 出现了异步请求发送了无限次的问题,翻🚗了。我有个组件大概是这么写的:

jsx 复制代码
import React, { useState, useEffect } from 'react';

import request from 'umi-request';

import logo from './logo.svg';
import './App.css';

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    request('https://jsonplaceholder.typicode.com/todos/', {
     method: 'get',
    })
    .then(response => {
      console.log('fetch data');
      setData(response);
    })
    .catch(error => {
      console.log("report error: ", error);
    })
  });

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <ul>
          {data.map(item => {
            return (
            <li key={item.id}>{item.title}</li>
            );
          })}
        </ul>
      </header>
    </div>
  );
}

export default App;

效果如下:

{% iframe codesandbox.io/embed/nice-... 100% 500 %}

{% gallery %} {% endgallery %}

zo2c2.csb.app/,可以很方便的从调试控制台看到,异步请求一直在发,陷入了死循环之中。这是为什么?因为 useEffect 会在组件 Mounting 和 Updating 阶段执行。每次 request 请求成功,我们都会设置一次组件的 state -> data,所以组件会更新,useEffect 会再次执行,循环往复,造成了无限重复请求问题。那么,如何解决这个问题?之前我忽略了 useEffect 第二个参数的存在,使用 useEffect 的第二个参数可以解决这个问题。一般情况下,我们希望组件只在 mounting 阶段异步获取数据,所以,我们可以这么设置 useEffect 的第二个参数,让它具有和 componentDidMount 生命周期函数类似的行为(组件第一次 mount 后执行):

{% folding red open, React 组件生命周期 %}

来源:projects.wojtekmaj.pl/react-lifec...

{% endfolding %}

{% codeblock lang:jsx line_number:true mark:7,12 %} useEffect(() => { request('jsonplaceholder.typicode.com/todos/', { method: 'get', }) .then(response => { console.log('fetch data'); setData(response); }) .catch(error => { console.log("report error: ", error); }) }, []); {% endcodeblock %}

我们传递了一个空数组作为 useEffect 的第二个参数,这样就能避免在组件 Updating 阶段执行 useEffect。这个数组成为依赖数组。依赖数组为空,表明 useEffect 不会因为某个变量的变化而再次执行。在组件需要根据某个变量变化进行渲染的时候,可以将此变量放到依赖数组中,一旦这个依赖的变量变动,useEffect 就会重新执行。

让组件卸载后做点事

在 class 组件中,我们可以将组件卸载后要做的事放在 componentWillUnmount 中。引入 Hook 后,在 function 组件中,我们可以把组件卸载要做的事放在 useEffect 中,让它返回一个 callback 即可,如下:

jsx 复制代码
import React, { useState, useEffect } from "react";

function Child({ visible }) {
  useEffect(() => {
    alert("组件已挂载");
    return () => {  // return 一个 callback
      alert("组件已被卸载!!");
    };
  }, []);

  return visible ? "true" : "false";
}

export default function App() {
  const [visible, changeVisible] = useState(true);

  return (
    <div>
      {visible && <Child visible={visible} />}
      <button
        onClick={() => {
          changeVisible(!visible);
        }}
      >
        {visible ? "卸载组件" : "挂载组件"}
      </button>
    </div>
  );
}

{% iframe codesandbox.io/embed/conde... 100% 500 %}

{% gallery %} {% endgallery %}

参考

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
javaDocker4 小时前
业务架构、数据架构、应用架构和技术架构
架构
JosieBook6 小时前
【架构】主流企业架构Zachman、ToGAF、FEA、DoDAF介绍
架构
.生产的驴7 小时前
SpringCloud OpenFeign用户转发在请求头中添加用户信息 微服务内部调用
spring boot·后端·spring·spring cloud·微服务·架构
丁总学Java7 小时前
ARM 架构(Advanced RISC Machine)精简指令集计算机(Reduced Instruction Set Computer)
arm开发·架构
ZOMI酱9 小时前
【AI系统】GPU 架构与 CUDA 关系
人工智能·架构
天天扭码16 小时前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
余生H17 小时前
transformer.js(三):底层架构及性能优化指南
javascript·深度学习·架构·transformer