React:组件功能的副作用与效果之间的区别?

React: Difference between side effect in component's function vs effect?

我试图理解在组件函数中产生副作用与在没有传入依赖项数组的效果中产生副作用(因此应该在每次渲染时触发)之间的实际区别。据我观察,它们 运行 的频率相同。我意识到效果允许在适当的时间进行清理,但我只是对清理不是一个因素的情况感到好奇。

下面的CodePen说明了我在说什么。

https://codepen.io/benrhere/pen/GRyvXZZ

重要的部分是:

function EffectVsFunctionQuestion() {
  const [count, setCount] = React.useState(0);

  React.useEffect(()=>{
    console.log("incremented within hook")
  });
  console.log("incremented within component function")
...
}

本质上,useEffect 钩子确保代码不会 运行,直到 DOM 为 mounted/updated。如果您 运行 在它之外编写代码,它可以在 DOM 呈现之前调用,这可能会导致问题。它不会阻止内容呈现,因为它是在呈现之后调用的。它等同于之前几个基于 class 的生命周期方法(ComponentDidMount 等)。 Docs

useEffect 挂钩发出的

Side-effects 的优点是每次渲染最多 触发一次循环。这里的渲染周期意味着 React 计算下一个视图并将其提交到 DOM.

时的“提交阶段”

不应该与 React 在渲染组件时所谓的“渲染阶段”混淆( 和 children 以及整个 ReactTree) 来计算更改的内容和需要提交给 DOM.

的内容

一个React函数组件的整个函数体 “渲染”功能。正如您在图中看到的那样,render 或正文中的任何无意 side-effects 都将发生在可以暂停、中止或重新启动的“渲染阶段”(,即 运行 再次 ) 通过 React。请注意,“渲染阶段”是纯粹的并且没有 side-effects.

组件可以与 DOM 和 运行 side-effects.

一起工作的“提交阶段”

Why does this matter? How to tell the difference.?

React 实际上附带了一个 StrictMode component 可以帮助您检测意外 side-effects.

Detecting unexpected side effects

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:

  • Class component constructor, render, and shouldComponentUpdate methods
  • Class component static getDerivedStateFromProps method
  • Function component bodies
  • State updater functions (the first argument to setState)
  • Functions passed to useState, useMemo, or useReducer

这是一个演示意外副作用的示例沙盒演示。

请注意,意想不到的效果加倍了。

代码:

const externalValue1 = { count: 0 };
const externalValue2 = { count: 0 };

function EffectVsFunctionQuestion() {
  const [state, setState] = React.useState(0);

  React.useEffect(() => {
    externalValue1.count++;
    console.log("incremented within hook", externalValue1.count);
  });
  externalValue2.count++;
  console.log("incremented within component function", externalValue2.count);

  return (
    <button type="button" onClick={() => setState((c) => c + 1)}>
      Render
    </button>
  );
}