且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-01-16 17:37:13

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

What are the advantages and use cases of the Effect hook (useEffect())?

优势

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

Advantages

Primarily, hooks in general enable the extraction and reuse of stateful logic that is common across multiple components without the burden of higher order components or render props.

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

A secondary benefit (of Effect hooks in particular) is the avoidance of bugs that might otherwise arise if state-dependent side effects are not properly handled within componentDidUpdate (since Effect hooks ensure that such side effects are setup and torn-down on every render).

另请参见下文中的性能和可读性优点.

See also the peformance and readability benefits detailed below.

 

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

Any component that implements stateful logic using lifecycle methods—the Effect hook is a "Better Way".

 

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

Why would it be preferable & how does it differ over componentDidMount/componentDidUpdate/componentWillUnmount (performance/readability)?

为什么更合适

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

Why it's preferable

Because of the advantages detailed above and below.

 

效果挂钩—

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

 

效果挂钩会导致:

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

  • simpler and more maintainable components, owing to an ability to split unrelated behaviour that previously had to be expressed across the same set of lifecycle methods into a single hook for each such behaviour—for example:

componentDidMount() {
  prepareBehaviourOne();
  prepareBehaviourTwo();
}

componentDidUnmount() {
  releaseBehaviourOne();
  releaseBehaviourTwo();
}

成为:

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

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

请注意,与 BehaviourOne 相关的代码现在已与与 BehaviourTwo 相关的代码明显分开,而之前已将其混入每个生命周期方法中.

Notice that code relating to BehaviourOne is now distinctly separated from that relating to BehaviourTwo, whereas before it was intermingled within each lifecycle method.

样板,因为不需要在多个生命周期方法中重复相同的代码(例如, componentDidMount componentDidUpdate 之间常见)例如:

less boilerplate, owing to an elimination of any need to repeat the same code across multiple lifecycle methods (such as is common between componentDidMount and componentDidUpdate)—for example:

componentDidMount() {
  doStuff();
}

componentDidUpdate() {
  doStuff();
}

成为:

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