React渲染严格模式与非严格模式

时间:2020-10-21 06:09:01

标签: reactjs

docker run -p 80:80 [name]

当我同时在和非严格模式下运行代码时,我得到了以下内容,

without strict mode

with strict mode

我希望处于非严格模式的第一个控制台日志是一个空数组,因为useEffect是在初始呈现后运行的,非严格模式是否跳过了初始呈现阶段,还是其他原因导致第一个控制台以非严格模式登录不是一个空数组吗?

2 个答案:

答案 0 :(得分:2)

这与严格或非严格模式无关,而是与控制台日志缓冲区刷新到输出的时间有关。由于进行了额外的检查,因此在严格模式下运行比在非严格模式下慢。因此,控制台日志输出的视图可能会有所不同。

请注意,console.log()输出与代码执行不同步。按照执行顺序,您应该期望所有控制台日志输出都是一个空数组。但这不是您所看到的,因为当您使用console.log(temp)时,在记录数组时您看不到数组的值。

如果使用console.log(JSON.parse(JSON.stringify(temp))),您将看到所有控制台输出为空数组。

您可以参考mozilla's recommendation记录对象:

不要使用console.log(obj),请使用 console.log(JSON.parse(JSON.stringify(obj)))。

这样,您可以确定当前正在查看obj的值 你记录下来。否则,许多浏览器会提供实时视图, 随着价值的变化而不断更新。这可能不是您想要的。

答案 1 :(得分:1)

不,我认为使用reacts StrictMode组件时会看到预期的效果。

Detecting unexpected side effects

React确实有两个阶段起作用,即“渲染”阶段和“提交”阶段。

  • 渲染阶段确定需要对哪些内容进行更改,例如DOM。在此阶段,React调用render,然后比较 结果到以前的渲染。
  • 提交阶段是React应用任何更改的时间。 (对于React DOM,这是React插入,更新和删除DOM的时间 节点。)React还调用生命周期,例如componentDidMountcomponentDidUpdate在此阶段。

在提交之前,React可以多次调用渲染阶段。

严格模式无法自动为您检测副作用,但是 可以使它们更具确定性,从而帮助您发现它们。 这是通过有意重复调用以下功能来完成的:

  • 类组件的构造函数,呈现器和shouldComponentUpdate方法
  • 类组件的静态getDerivedStateFromProps方法
  • 功能组件主体
  • 状态更新程序功能(setState的第一个参数)
  • 传递给useState,useMemo或useReducer的函数

整个功能组件主体是“渲染”功能。该效果在“提交”阶段作为“生命周期函数”运行。

Edit react-render-strict-mode-vs-non-strict-mode

此演示同时显示了两者。

  1. 请注意,with-StrictMode组件中有多个控制台日志,但是只有两个带有no-StrictMode组件的控制台日志。
  2. 如果您注释掉useEffect钩并重新运行沙箱,请注意,Strictmode包装的应用程序进行了两次日志记录,而未包装的应用程序进行了一次日志记录。

您会看到,从“渲染”阶段开始,至少 个日志(如果在StrictMode中运行,则至少一个),并且 总是准确 来自useEffect的一个日志,该日志在每个渲染周期(即“提交”阶段)运行一次。

可能还会使问题复杂化的事实是,您正在对数组引用进行突变,并且在刷新控制台日志缓冲区以输出时,有可能使用新值对其进行了突变。请记住,返回中的第二个控制台日志等效于“ render”函数中的副作用,后者应为纯函数。有了这种副作用,将会产生意想不到的结果,这当然是StrictMode的重点。