zoukankan      html  css  js  c++  java
  • react hook 的 useEffect 副作用

    前言

    在 react 的 16.8 版本中 引入了 hook 概念,这是一次翻天覆地的改变,是一次理念的改变,也可以说是推到重建


    本文的目的

    在开始写本文之前,一直在考虑要不要对比旧版本的react,也就是 class component(hook 被称为 function component)。因为对比着更容易找到异同点,更容易上手去使用。
    但是,react hook 是一次完全的更新换代,理念也改变,对比 class 进行介绍,可以说是一种误导。
    所以,这段话写在前面,希望各位读者可以对比着快速上手,但是在理解hook时,请不要用旧版本的那一套去理解


    旧版本的react(v16.8以前)

    旧版的react也就是 class component,当然新版本中仍然还兼容着class 用法

     class ListPage extends Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0,
        };
        console.log('constructor');
      }
    
      componentWillMount() {
        console.log('componentWillMount');
      }
    
      componentDidMount() {
        console.log('componentWillMount');
      }
    
      componentDidUpdate() {
        const { count } = this.state;
        console.log('componentDidUpdate, count', count);
      }
    
      componentWillUnmount() {
        console.log('componentWillUnmount');
      }
    
      render() {
        console.log('render');
        const { count } = this.state;
        return(
          <div>
            <span> { count } </span>
            <button onClick={() => this.setState({count: count + 1})}>增加count</button>
          </div>
        )
      }
    }
    

    初次渲染时,打印的log:

    constructor
    componentWillMount
    render
    componentDidMount
    

    state改变时,打印的log:

    componentWillUpdate
    render
    componentDidUpdate
    

    新版本的 function Component 的 用法(即 hook)

    useEffect,副作用,可以看做是 componentDidMount componentDidUpdate componentWillUnmount 三个函数的组合,但最好不要使用生命周期那一套来理解

    const Home = () => {
      const [count, setCount] = useState(0);
    
      useEffect(() => {
        console.log('useEffect 1');
    
        return () => {console.log('useEffect 2');}
      }, [])
    
      useEffect(() => {
        console.log('useEffect 3');
    
        return () => {console.log('useEffect 4');} 
      }, [count])
      
      console.log('render')
    
      return(
        <div>
          <span>{count}</span>
          <button onClick={() => setCount(count + 1)}>增加count</button>
        </div>
      )
    }
    

    初次渲染时,打印的log:

    render
    useEffect 1
    useEffect 3
    

    state改变时,打印的log:

    render
    useEffect 4
    useEffect 3
    

    通过上面的log我们可以发现:

    1. useEffect 可以模拟出上文所说的 三个声明周期(componentDidMount componentDidUpdate componentWillUnmount)
      componentWillUnmount 暂未使用log尝试(log('useEffect 2')所在的回调中能够完整代替 componentWillUnmount)
    2. class component 和 function component 比较可以发现:并没有完全的契合
    3. log('useEffect 1') 虽然可以模拟出 componentDidMount,但其他的log('useEffect 3')也会触发
    4. 可以发现 function component 中已经没有了 will的生命周期(比如willMount、willUpdate)

    useEffect

     useEffect(() => {
        console.log('useEffect 1');
    
        return () => {console.log('useEffect 2');}
      }, [])
    
      useEffect(() => {
        console.log('useEffect 3');
    
        return () => {console.log('useEffect 4');} 
      }, [count])
    

    useEffect 钩子有两个参数,参数一是function,参数二是array数组,通过这两个参数可以实现function component不同的情景

    1. 如果参数二不传参
      包括初始执行、state改变,参数一的function回调都会执行
    2. 如果参数二传参空数组
      只在初始时执行参数一的function回调
    3. 如果参数二传有值得数组
      初始时,或者参数二数组中值改变时,都会执行参数一的function回调

    注意: 参数一的function回调,可以有返回值(也是function回调)
    如果参数二传入的是空数组,此处返回值的回调即可代表 componentWillUnmount,即在function销毁时执行


    最后:

    1. useEffect 与其看做是三个生命周期函数的集合,不如看做每次渲染后都会执行的副作用(初始化、state改变时都会重新渲染)
    2. 每次render 都有自己的 props 和 state,就像快照,每一个render瞬间都有自己独立的function
      所以不要想着在 每一个快照中都能拿到 最新的state,如下的count:
     useEffect(() => {
        const id = setInterval(() => {
          setCount(count + 1);
          // 此处打印始终是1,因为count绑定了初次进入的值
          console.log('count', count)
          // 调整为此即可,或者将count放入参数二的数组中(但这样会导致计算器的频繁创建和销毁)
          // setCount(preCount => preCount + 1)
        }, 1000);
        return () => clearInterval(id);
     }, []);
    

    参考

    精读《useEffect 完全指南》: https://www.cnblogs.com/ascoders/p/10591832.html

  • 相关阅读:
    java中的socket编程有关printStream的println方法和write方法
    json在php中的用法
    js的数组处理函数splice
    将博客搬至CSDN
    mapreduce导出MSSQL的数据到HDFS
    基于信息熵的无字典分词算法
    搜索引擎手记(三)之网页的去重
    算法之常用的距离和相似度度量
    搜索引擎手记(二)之爬虫的开发
    搜索引擎手记(一)之引擎工作的开始
  • 原文地址:https://www.cnblogs.com/nangezi/p/15732671.html
Copyright © 2011-2022 走看看