ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

react hook 的 useEffect 副作用

2021-12-26 13:05:23  阅读:199  来源: 互联网

标签:count function console log react hook state 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);
 }, []);

标签:count,function,console,log,react,hook,state,useEffect
来源: https://www.cnblogs.com/nangezi/p/15732671.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有