27

关于新提出的React Effect Hook

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

  2. 为什么它会更好?它在componentDidMount/componentDidUpdate/componentWillUnmount(性能/可读性)方面有何不同?

该文件指出:

函数组件的主体(称为 React 的渲染阶段)中不允许发生突变、订阅、计时器、日志记录和其他副作用。

但我认为在 componentDidUpdate 等生命周期方法中而不是在 render 方法中具有这些行为已经是常识。

还有人提到:

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

但这不是做什么componentDidMountcomponentDidUpdate做的吗?

4

3 回答 3

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

    优点

    首先,钩子通常可以提取和重用跨多个组件通用的有状态逻辑,而无需高阶组件或渲染道具的负担。

    第二个好处(特别是 Effect 钩子)是避免了如果在内部没有正确处理依赖于状态的副作用可能会出现的错误componentDidUpdate(因为 Effect 钩子确保在每次渲染时设置和删除此类副作用)。

    另请参阅下文详述的性能和可读性优势。

     

    用例

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

     

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

    为什么它更可取

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

     

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

    表现

    效果挂钩——</p>

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

     

    可读性

    效果挂钩导致:

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

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

      变成:

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

      请注意,与 相关的代码BehaviourOne现在与 与 相关的代码明显分开BehaviourTwo,而在此之前,它混合在每个生命周期方法中。

    • 由于消除了跨多个生命周期方法重复相同代码的任何需要(例如在componentDidMountand之间很常见componentDidUpdate),因此样板代码更少——例如:

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

      变成:

      useEffect(doStuff); // you'll probably use an arrow function in reality
      
于 2018-10-29T19:48:05.397 回答
12

这是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>
  );
}
于 2018-10-29T18:32:52.227 回答
2

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>
  );
}
```
于 2020-10-19T10:07:14.757 回答