React钩子:什么/为什么使用useEffect?

时间:2018-10-29 18:12:16

标签: javascript reactjs react-hooks

关于新提议的React Effect Hook;

  1. Effect钩子(useEffect())的优点和用例是什么?

  2. 为什么会更可取?与componentDidMount/componentDidUpdate/componentWillUnmount(性能/可读性)有何不同?

文档指出:

  

在功能组件的主体内(称为React的渲染阶段),不允许进行突变,订阅,计时器,日志记录和其他副作用。

但是我认为,在生命周期方法(例如componentDidUpdate等)中使用这些行为而不是render方法已经是常识。

也有提到:

  

传递给useEffect的函数将在将渲染提交到屏幕后运行。

但这不是componentDidMountcomponentDidUpdate所做的吗?

3 个答案:

答案 0 :(得分:5)

这是 ReactConf2018 丹·阿布拉莫夫(Dan Abramov)的演讲中的一个例子,解释了其中的区别:


以下是以下示例的一些发现:

  1. 您将使用钩子编写更少的样板代码
  2. 使用useEffect()访问生命周期更新和状态更新
  3. 关于性能方面是:
  

与componentDidMount和componentDidUpdate不同,传递给useEffect的函数会在延迟事件期间进行布局和绘制后触发

  1. 代码共享太简单了,并且可以在同一组件中为不同目的多次实现useEffect()。
  2. 您可以通过将数组作为第二个参数传递到useEffect()钩子来控制组件的重新渲染,这在您仅传递空数组[]仅在安装和卸载时渲染组件时非常有效。
  3. 使用多个useEffect()钩子来分离问题并做出反应:
  

Hooks让我们根据代码的工作方式而不是生命周期方法名称来拆分代码。 React将按照指定的顺序应用组件使用的所有效果


使用课程:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }

  componentDidUpdate() {
    document.title = `You clicked ${this.state.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>
    );
  }
}

使用挂钩:

import { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

答案 1 :(得分:5)

  1.   

    Effect钩子(useEffect())的优点和用例是什么?

    优势

    从根本上讲,钩子通常可以提取和重用在多个组件之间通用的状态逻辑,而无需负担高阶组件或渲染道具。

    (尤其是效果钩子)的第二个好处是避免了在componentDidUpdate中不能正确处理与状态相关的副作用的情况下可能会出现的错误(因为效果钩子确保可以设置和配置此类副作用)在每个渲染器上都拆下。)

    另请参见下面详细介绍的性能和可读性优点。

    用例

    任何使用生命周期方法实现状态逻辑的组件-Effect挂钩都是一种“更好的方式”。

  2.   

    为什么会更受欢迎?与componentDidMount / componentDidUpdate / componentWillUnmount(性能/可读性)相比有何不同?

    为什么更合适

    由于上面和下面详述的优点。

    它与生命周期方法有何不同

    性能

    效果钩子

    • 感觉比生命周期方法响应更快,因为它们不会阻止浏览器更新屏幕;
    • 但是,将在每个渲染上设置和删除副作用,这可能会很昂贵……
    • …因此可以优化为完全跳过,除非已更新特定状态。

    可读性

    效果挂钩会导致:

    • 更简单,更易于维护的组件,因为能够将以前必须在同一生命周期方法集中表达的不相关行为拆分为每个此类行为的单个钩子,例如:

      componentDidMount() {
        prepareBehaviourOne();
        prepareBehaviourTwo();
      }
      
      componentDidUnmount() {
        releaseBehaviourOne();
        releaseBehaviourTwo();
      }
      

      成为:

      useEffect(() => {
        prepareBehaviourOne();
        return releaseBehaviourOne;
      });
      
      useEffect(() => {
        prepareBehaviourTwo();
        return releaseBehaviourTwo;
      });
      

      请注意,与BehaviourOne相关的代码现在已与与BehaviourTwo相关的代码明显分开,而之前却被混入了每种生命周期方法中。

      减少了
    • 样板,这是因为不需要在多个生命周期方法中重复相同的代码(例如componentDidMountcomponentDidUpdate之间很常见),例如:

      componentDidMount() {
        doStuff();
      }
      
      componentDidUpdate() {
        doStuff();
      }
      

      成为:

      useEffect(doStuff); // you'll probably use an arrow function in reality
      

答案 2 :(得分:1)

useEffect在状态更改时运行。

import { useState, useEffect } from 'react';
function Example() {
  const [Age, setAge] = useState(33);
  const [Somestate,setSomestate]=useState(initilaestate);
  useEffect(() => {
    console.log('the age is changed to ',Age);
  });

// you can use useEffect as many times you want in you component 
  useEffect(() => {
    console.log('the age is changed to ',Age);
  },[someState]);//here you tell useEffect what state to watch if you want to watch the changing of a  particular state and here we care about someState
  return (
    <div>
      <p>age increased to  {Age}</p>
      <button onClick={() => setAge(count + 1)}>
       Increase age by One
      </button>
    </div>
  );
}
```