美文网首页Web前端之路
React Effect Hook用法详解

React Effect Hook用法详解

作者: 前端家园 | 来源:发表于2019-10-08 16:49 被阅读0次

    useEffect简介

    useEffect,字面意思可以理解为"执行副作用操作",对比于以前react class的写法,可以把 useEffect看做 componentDidMountcomponentDidUpdatecomponentWillUnmount 这三个函数的组合。

    为了便于理解useEffect到底是个什么东西,我们来对比下class的写法和useEffect的写法

    class组件写法
    class Example extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0
        };
      }
    
      componentDidMount() {
        console.log(`You clicked ${count} times`);
      }
    
      componentDidUpdate() {
        console.log(`You clicked ${count} times`);
      }
    
      render() {
        return (
          <div>
            <p>You clicked {this.state.count} times</p>
            <button onClick={() => this.setState({ count: this.state.count + 1 })}>
              Click me
            </button>
          </div>
        );
      }
    }
    
    useEffect组件写法
    import React, { useState, useEffect } from 'react';
    
    function Example() {
      const [count, setCount] = useState(0);
    
      // 相当于 componentDidMount 和 componentDidUpdate
      useEffect(() => {
        console.log(`You clicked ${count} times`);
      });
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
        </div>
      );
    }
    
    注意点
    1. useEffect会在每次渲染后都执行,也就是说在第一次渲染之后和每次更新之后都会执行。
    2. useEffect执行的effect是异步的,不会阻塞浏览器更新屏幕,但是在某些场景下这种异步的方式可能并不合适,比如初始布局场景,这个时候可能需要用到useLayoutEffect(与useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect)。
    清除effect

    React class中,我们通常会在componentDidMount 中设置订阅,并在componentWillUnmount中清除它,那么在useEffect中设置的订阅,我们如何清除呢?

    我们可以在useEffect的回调函数中返回一个函数,React 将会在执行清除操作时调用它。

    useEffect(() => {
      function handleScroll() {console.log('scroll')}
      window.addEventListener('scroll', handleScroll)
      // 相当于componentWillUnmount
      return function cleanup() {
        window.removeEventListener('scroll', handleScroll)
      };
    });
    
    
    effect参数

    在上面我们介绍到可以通过返回一个函数来实现componentWillUnmount的功能,从而实现解绑事件等功能,但是细心的同学可能会发现上面的例子有个问题,就是每次重新渲染的时候,这个useEffect回调就会触发,从而不断的进行绑定,解绑,这显然不是我们想要的,那么如何实现像componentDidMountcomponentWillUnmount那样只执行一次呢?这里就需要用到useEffect的第二个参数了。

    1. 如果什么都不传,那么每次渲染都会执行。
    2. 如果传一个空数组,那么就只会运行一次effect,并且effect内部的 propsstate 会一直拥有其初始值。
    3. 如果传的是一个包含属性值的数组,那么只有当数组里的值发生变化的时候才会触发useEffect回调。
    每次都触发
    // 相当于 componentDidMount 和 componentDidUpdate
    useEffect(() => {
      console.log(`You clicked ${count} times`);
    });
    
    只需要触发一次
    // 由于第二个参数传的是空数组,所以这里相当于componentDidMount
    useEffect(() => {
      function handleScroll() {}
      window.addEventListener('scroll', handleScroll)
      // 相当于componentWillUnmount
      return function cleanup() {
        window.removeEventListener('scroll', handleScroll)
      };
    }, []);
    
    当属性值变化时才触发
    import React, { useState, useEffect } from 'react';
    
    function Example() {
      const [count, setCount] = useState(0);
      const [show, setShow] = useState(false);
    
      // 只有当count发生变化的时候才会触发,show发生变化不会触发
      useEffect(() => {
        console.log(`You clicked ${count} times`);
      }, [count]);
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
          <button onClick={() => setShow(!show)}>
            Toggle show
          </button>
        </div>
      );
    }
    

    相关文章

      网友评论

        本文标题:React Effect Hook用法详解

        本文链接:https://www.haomeiwen.com/subject/nzabpctx.html