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

Ben*_*iFB 3 javascript reactjs react-hooks use-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")
...
}
Run Code Online (Sandbox Code Playgroud)

Dre*_*ese 5

从钩子发出的副作用的useEffect优点是每个渲染周期最多触发一次。这里的渲染周期是指 React 计算出下一个视图并将其提交到 DOM 时的“提交阶段”。

\n

不应该与 React 所谓的“渲染阶段”混淆,当它渲染出组件(以及子组件和整个 ReactTree)以计算发生了什么变化并需要提交给 DOM 时。

\n

在此输入图像描述

\n

React 函数组件的整个函数体就是“render”函数。正如您在图中所看到的,或主体中的任何无意的副作用render都会在“渲染阶段”发生,可以通过 React 暂停、中止或重新启动(即再次运行)。请注意,“渲染阶段”是纯粹的并且没有副作用。

\n

在“提交阶段”,组件可以使用 DOM 并运行副作用。

\n
\n

为什么这很重要?如何辨别?

\n
\n

React 实际上附带了一个StrictMode组件,可以帮助您检测意外的副作用。

\n

检测意外的副作用

\n
\n

严格模式可以\xe2\x80\x99t 自动为您检测副作用,但它\n可以通过使副作用更具确定性来帮助您发现它们。\n这是通过有意两次调用以下函数来完成的:

\n
    \n
  • 类组件 constructor rendershouldComponentUpdate方法
  • \n
  • 类组件静态getDerivedStateFromProps方法
  • \n
  • 功能组件体
  • \n
  • 状态更新器函数( 的第一个参数setState
  • \n
  • 传递给useStateuseMemo、 或 的函数useReducer
  • \n
\n
\n

这是一个示例沙盒演示,演示了意想不到的副作用。

\n

编辑组件函数与效果中副作用之间的反应差异

\n

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

\n

在此输入图像描述

\n

代码:

\n
const externalValue1 = { count: 0 };\nconst externalValue2 = { count: 0 };\n\nfunction EffectVsFunctionQuestion() {\n  const [state, setState] = React.useState(0);\n\n  React.useEffect(() => {\n    externalValue1.count++;\n    console.log("incremented within hook", externalValue1.count);\n  });\n  externalValue2.count++;\n  console.log("incremented within component function", externalValue2.count);\n\n  return (\n    <button type="button" onClick={() => setState((c) => c + 1)}>\n      Render\n    </button>\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n