严格的模式与React 18的工作方式不同吗?
考虑下面的摘要。使用React 18, Count
在每个渲染上都将两次打印到控制台,但使用React 17仅打印一次。
反应18示例:
function App() {
const [count, setCount] = React.useState(0);
console.log(count);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>
反应17示例
function App() {
const [count, setCount] = React.useState(0);
console.log(count);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
我知道这与 strictmode
有关,但我不确定是什么。而且,我一直不清楚严格模式的工作原理以及其目的是什么,因此,如果有人也能强调这一点,我将不胜感激。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
tl; dr
当组件用
strictmode
包裹时,React将两次运行某些功能,以帮助开发人员在其代码中捕获错误。这既是在React 18和React 17中都发生的,但是您之所以没有使用后者遇到的原因是因为在React 17中,React自动在第二个呼叫中自动沉默日志。
如果您提取
console.log
并使用提取的别名进行日志,那么您将获得两个版本的类似行为。现在让我们深入了解严格模式中实际发生的事情及其有用。
严格模式
严格模式是一种工具,可以帮助识别与React一起使用时可能引起问题的编码模式,例如不纯粹的渲染。
在开发中严格模式下,React在两次中运行以下功能:
,这是因为您的组件,初始化器&amp;更新器需要为 纯函数 ,但是如果不是,那么< em>双击它们可能有助于遇到这个错误。如果它们是纯净的,那么您的代码中的逻辑不会以任何方式影响。
注意: React仅使用一个呼叫的结果,而忽略了另一个呼叫的结果。
在下面的示例中,观察到组件,初始化器&amp;在开发过程中,更新器在
strictmode
中运行两次(摘要使用React的开发构建)。上面的示例中有几笔注释:
您可能已经注意到,当您第一次单击按钮时,
更新程序运行两次
log仅一次打印一次,但随后单击后续单击它打印两次。但是您可以忽略此行为,并假设它总是打印两次,但是如果您想要更多有关相同的详细信息,则可以按照此操作 github问题。我们必须将
console.log
提取到一个单独的变量中,以获取打印的调用的日志,这是因为react 17自动沉默了第二个呼叫的日志(如TL中提到; )。如果将CDN链接更新为React 18,则不需要此提取。调用
setCount
updater函数两次并不意味着它现在每次点击两次都会增加count
no ,因为它在两次时都将更新程序调用相同状态。因此,只要您的更新器是纯函数,您的应用程序就不会受到NO的影响。被称为。“ Updaters”&amp; “初始化器”是React中的通用术语。状态更新者&amp;状态初始化只是众多。其他更新程序是传递给
usememo
和“ reducers”的“回调”。另一个初始化器是用户eDucer
initializer等。所有这些 纯粹的函数如此严格的模式double double调用所有功能。结帐此示例:严格模式如何有帮助?
让我们看一个示例,严格模式将帮助我们找到一个严重的错误。
上面的示例有什么问题?
您会注意到按钮无法正常工作,它们不会切换
iscomplete
boolean,问题是更新程序函数传递给settodos
是不是纯函数,因为它在todos
状态中突变对象。而且由于更新程序被称为两次,并且不是纯函数,因此第二个调用将iscomplete
布尔值逆转为原始值。注意:仅仅是因为严格的双重调用,我们才能够捕获这个错误。如果我们选择退出严格的模式,那么组件幸运的是 的工作原理,但这并不意味着代码是正确撰写的,仅由于组件的隔离程度,并且在现实世界中的情况下起作用这样的突变会导致严重的问题。即使您幸运地摆脱了这样的突变,您仍然可能会遇到问题,因为当前更新程序依赖于每次点击仅调用一次,但这是不是 反应保证的东西(考虑并发功能)。
如果将更新程序作为纯函数,它将解决问题:
React 18中的React 18中的新事物是什么,'
react 18,'
strictmode
&nbsp;是否有一个额外的行为,以确保其与可重复使用的状态兼容。当启用严格模式时,&nbsp; 有意反应新安装的组件考虑下面的示例( source ):
App
上面的组件声明了一些要在安装座上运行的效果。在React 18之前,设置函数只能运行一次(在最初安装组件之后),并且清理功能也只能运行一次(在组件未填充之后)。但是在strictmode
中的React 18中,将发生以下情况:建议的读数
TL;DR
When components are wrapped in
StrictMode
, React runs certain functions twice in order to help developers catch mistakes in their code.And this happens both in React 18 and React 17 but the reason you aren't experiencing this with the latter is because in React 17, React automatically silences logs in the second call.
If you extract out
console.log
and use the extracted alias to log, then you would get similar behavior with both versions.Now let's dive deep to understand what actually happens in strict mode and how it can helpful.
Strict Mode
Strict Mode is a tool that helps identify coding patterns that may cause problems when working with React, like impure renders.
In Strict Mode in development, React runs the following functions twice:
And this is because your components, initializers & updaters need to be pure functions but if they aren’t then double-invoking them might help surface this mistake. And if they are pure, then the logic in your code is not affected in any manner.
Note: React uses the result of only one of the calls, and ignores the result of the other.
In the example below observe that components, initializers & updaters all run twice during development when wrapped in
StrictMode
(snippet uses the development build of React).Few notes from the above example:
You might have noticed that when you click the button for the first time the
Updaters run twice
log prints only once but on subsequent clicks it prints twice. But you can ignore this behavior and assume that it always prints twice but if you want more details about the same you can follow this github issue.We had to extract
console.log
into a separate variable to get logs for both the invocations printed and this is because React 17 automatically silences logs for the second call (as mentioned in the TL;DR). If you update the CDN link to React 18, then this extraction wouldn't be required.Calling the
setCount
updater function twice doesn’t mean that it would now increment thecount
twice on every click, no, because it calls the updater with the same state both the times. So, as long as your updaters are pure functions, your application wouldn’t get affected by the no. of times it’s called."Updaters" & "Initializers" are generic terms in React. State updaters & state initializers are just one amongst many. Other updaters are "callbacks" passed to
useMemo
and "reducers". Another initializers isuseReducer
initializer etc. And all of these should be pure functions so strict mode double invokes all of them. Checkout this example:How is Strict Mode helpful?
Let's look at an example where Strict Mode would help us find a serious mistake.
What's the problem with the above example?
You would've noticed that the buttons don't work as expected, they don't toggle the
isComplete
boolean and the problem is that the updater function passed tosetTodos
is not a pure function as it mutates an object in thetodos
state. And since the updater is called twice, and it is not a pure function, the second call reverses theisComplete
boolean back to it’s original value.Note: It's only because of strict mode's double invocation that we were able to catch this mistake. If we opt out of strict mode, then the component would luckily work as expected but that doesn't mean the code is authored correctly, it only works because of how isolated the component is and in real world scenarios mutations like these can cause serious issues. And even if you luckily get away with such mutations, you might still encounter problems because currently the updater relies on the fact that it's only called once for every click but this is not something that React guarantees (with concurrency features in mind).
If you make the updater a pure function, it would solve the issue:
What's new with Strict Mode in React 18
In React 18,
StrictMode
gets an additional behavior to ensure it's compatible with reusable state. When Strict Mode is enabled, React intentionally double-invokes effects (mount -> unmount -> mount) for newly mounted components. This is to ensure that a component is resilient to being "mounted" and "unmounted" more than once. Like other strict mode behaviors, React only does this for development builds.Consider the example below (Source):
The
App
component above declares some effects to be run on mount and unmount. Prior to React 18, the setup functions would only run once (after the component is initially mounted) and the cleanup functions would also run only once (after the component is unmounted). But in React 18 inStrictMode
, the following would happen:Suggested Readings
React 18的区别在于它现在显示了双效率。如果使用“ React Developer Tools” Chrome扩展名,则可以看到来自严格模式的日志:
The difference of React 18 is it is now showing the double renderings. If you are using "React Developer Tools" chrome extension with, you can see that which logs are coming from strict mode: