【问题标题】:React hooks: What/Why `useEffect`?反应钩子:什么/为什么`useEffect`?
【发布时间】:2019-04-02 17:41:19
【问题描述】:

关于新提出的React Effect Hook

  1. Effect 钩子 (useEffect()) 有哪些优点和用例?

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

文档指出:

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

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

还有人提到:

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

但这不是componentDidMountcomponentDidUpdate 做的吗?

【问题讨论】:

  • 您能否将您的问题与文档中您不理解的部分进行比较?
  • @MarkC。添加了更多信息以使问题不那么广泛。
  • 如果当前文档不清楚,您可以在官方 repo 中提出您的问题。官方文档还要求读者向 github 提出任何问题作为反馈。这不太适合这里。您可能会在此处获得所有可用博客文章摘要的所有答案。你已经得到了这样的答案。但是,如果您确实在官方 repo 中询问,并且他们认为文档需要更新,它就会发生。这样做会有很多人会有所帮助。

标签: javascript reactjs react-hooks


【解决方案1】:
  1. Effect 钩子 (useEffect()) 有哪些优点和用例?

    优势

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

    第二个好处(特别是 Effect 挂钩)是避免在 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】:

    这是 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>
        );
      }
    }
    

    使用 Hooks:

    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>
      );
    }
    

    【讨论】:

      【解决方案3】:

      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>
        );
      }
      ```
      

      【讨论】:

        猜你喜欢
        • 2021-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-20
        • 2020-09-01
        • 2021-06-02
        • 2020-08-08
        • 2021-07-02
        相关资源
        最近更新 更多