TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

PSA: React 18 calls code twice in strict dev mode to detect side effects

135 点作者 tomduncalf大约 3 年前

23 条评论

mbell大约 3 年前
&gt; In React 17, React automatically modifies the console methods like console.log() to silence the logs in the second call to lifecycle functions. However, it may cause undesired behavior in certain cases where a workaround can be used.<p>I feel like when you&#x27;ve gotten to the point that something like this has been proposed and accepted as a good solution to a problem your framework is facing, it may be a good time to stop and reconsider the approach of the framework.
评论 #30981858 未加载
评论 #30982129 未加载
评论 #30986100 未加载
评论 #30982569 未加载
评论 #30983908 未加载
评论 #30981871 未加载
Gravey大约 3 年前
Afaik this has been the behavior of StrictMode since it was introduced in React 16.<p>One thing that’s called out in the linked docs is that duplicate console.logs were _deliberately_ silenced in React 17. I have no idea what they were thinking when they made this decision, but it sounds like it has been walked back in 18.
评论 #30979355 未加载
评论 #30978260 未加载
评论 #30978326 未加载
评论 #30981983 未加载
评论 #30980799 未加载
评论 #30979333 未加载
tmpfs大约 3 年前
I recently wasted time figuring out why my code was getting executed twice and found this out the hard way. I think this is a particularly good example of overreach by Javascript developers and at the very least a console.warn could have notified me of this. I just removed strict mode as i think this is an awful side effect to implement. In my case, instead of helping me find bugs it had me hunting non-existent bugs, sigh.
tomduncalf大约 3 年前
I thought I’d share this in the hope that other developers see it and don’t lose a bunch of time wondering why e.g. code in a useEffect(…, []) block is being called twice.<p>I created a new Next.js project and was very confused to see my console.logs appearing twice. It might be nice for React to log a warning that it is going to do this as it’s quite confusing if you aren’t aware of it!
评论 #30983204 未加载
评论 #30978247 未加载
评论 #30977801 未加载
TAKEMYMONEY大约 3 年前
&gt; This only applies to development mode.
评论 #30980090 未加载
dataangel大约 3 年前
If they don&#x27;t want people to just end up depending on this behavior in a stateful way instead they should actually deliberately rely on non-determinism, call the functions a small random number of times.
评论 #30979731 未加载
LAC-Tech大约 3 年前
The fact that so many devs think react is a fundamental part of browser based applications has really pushed me away from front end. I used it for years and I just don&#x27;t see it.
评论 #30983710 未加载
sam0x17大约 3 年前
oh god, the horror of the fact that this is necessary! As someone who has largely and happily sidestepped the whole reactivity thing for the last decade, it really sounds like that whole world is starting to implode and contradict the very things it promised in the first place (simplicity). Please let web assembly deliver us out of this js-ridden mess \o&#x2F;
评论 #30981570 未加载
评论 #30981052 未加载
评论 #30981683 未加载
评论 #30981152 未加载
评论 #30982379 未加载
cpeterso大约 3 年前
To further restrict these component methods from having side effects, could React call these methods using a Proxy or eval() context that blocks these methods from reading or setting variables in the global context?
评论 #30980809 未加载
bob1029大约 3 年前
Blazor does something like this but for different reasons (ServerPrerendered mode for lower latency UX).<p>It took me a solid day to realize the behavior was intentional. There were no problems but it was one of those &quot;I cannot build an empire on these uncertain foundations&quot; moments.
marcus_cemes大约 3 年前
If anyone is curious as to why, I believe it&#x27;s the only way that React can &quot;poke&quot; your code to see whether it really is side-effect free, and therefore concurrent mode&#x2F;suspense compatible. The idea is that React can re-render your component whenever and however often it likes whilst getting the same results for the same input state, without this assumption, new patterns such as concurrent mode and suspense become very difficult to implement. Double rendering is a rudimentary dev-time test to see whether the output is actually the same to try and help you avoid bugs later on (data races for example), without enforcing a language, such as ReasonML or Elm. Alternatives would require really complex static analysis or strict ESLint rules. There may be other reasons as well.<p>Sometimes there&#x27;s a need for side effects, the DOM is very stateful and unfortunately React is not quite fast enough for smooth animations at 60fps on most devices, it&#x27;s also a lot easier to use global variables (no judgement) rather than properly organising state hooks and component props.<p>React started to move away from OOP and more towards FP, starting with hooks and function components. One of the driving reasons behind this was that function components could be minified a lot better than classes. Reducers, side effects, pure, memo, are terms that are more known in the FP land. I also think it gave them a lot more control as a framework to implement patterns such as concurrent mode as functions are stateless unlike classes, moving the state up into the React framework itself. This means several versions of the state can exist at once, and React just runs them through your function to generate the view. Side effects introduce unpredictability and nondeterminism using this pattern.<p>This FP style can be confusing to new programmers (anyone feel like trying to explain useEffect() to a 5-year-old? Anyone?), especially those that are used to global variables or manipulating the DOM directly (JQuery), but understanding the OOP render cycle had its own learning curve. Frameworks such as Elm are met with much love, even if React&#x27;s hook-based approach is a little different.<p>Small aside, I also think that&#x27;s where useEffect() got it&#x27;s name from: side effects. It&#x27;s where you put all those nasty network calls and setTimeout()s, and then scratch your head when you forgot to cancel&#x2F;unregister them when the component unmounts and React complains that you tried to change the state on an unmounted componment. Suspense (hence the need for side-effect free functions, hence this double-rendering problem) <i>should</i> help with avoiding putting &quot;if (stillMounted) { ... }&quot; everywhere in useEffects with async code by giving React more control over the render&#x2F;update process.<p>Full disclaimer, I haven&#x27;t actually written React in a while, not since I found out about Svelte, I&#x27;m curious, how to authors of libraries such as React&#x2F;Framer Motion handle the double rendering issue when interacting with the DOM directly? Other frameworks that I know of that avoid the complexities of concurrent mode&#x2F;suspense either very stricly enforce this FP style, such as Elm, or try to be fast enough to forgo the virtual DOM and embrace mutable state, events and two-way data binding such as Solid and Svelte.
评论 #30980339 未加载
评论 #30981891 未加载
davman大约 3 年前
Related:<p>I have an outstanding Bounty on a SO question for how to write a reusable useRef hook that only runs on the very first mount under StrictMode conditions:<p><a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;71695213&#x2F;equivalent-isfirstrender-hook-for-strictmode-in-development-mode" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;71695213&#x2F;equivalent-isfi...</a>
IceDane大约 3 年前
ITT a bunch of clowns who don&#x27;t know anything about React, haven&#x27;t written a single line of it in their lives and don&#x27;t care one whit for spending 10 seconds to understand why this is a useful feature, or how it isn&#x27;t even a new feature.<p>Never change, HN.
DustinBrett大约 3 年前
new-strict-mode-behaviors<p><a href="https:&#x2F;&#x2F;reactjs.org&#x2F;blog&#x2F;2022&#x2F;03&#x2F;29&#x2F;react-v18.html#new-strict-mode-behaviors" rel="nofollow">https:&#x2F;&#x2F;reactjs.org&#x2F;blog&#x2F;2022&#x2F;03&#x2F;29&#x2F;react-v18.html#new-stric...</a>
malkia大约 3 年前
That sounds really reactionary!
azangru大约 3 年前
Um, I remember StrictMode was running the code twice since forever. Probably since the time it was introduced in React 16-something. Has anything changed in React 18?
评论 #30981121 未加载
reverseblade2大约 3 年前
Off topic but anyway To all react devs, If you are not using web components (not mutually exclusively) then you are doing it wrong.
supermatt大约 3 年前
Pretty sure its been doing this in dev mode since 0.14. Maybe earlier...
评论 #30979764 未加载
评论 #30981918 未加载
sandwichinvest大约 3 年前
This, while unexpected, is not the end of the world.
评论 #30983992 未加载
baxuz大约 3 年前
It already did that since v16
jiggawatts大约 3 年前
I actually wish more languages did this kind of thing down to the compiler level. I see a lot of C code especially go through an &quot;evolution&quot; where it starts out being compatible with only one platform (typically x64) and then it slooooowly acquires wider compatibility one issue ticket at a time.<p>Wouldn&#x27;t it be great if all that <i>english</i> text in the language standard documents were enforced and&#x2F;or exercised at both compile time and (dev) runtime?<p>Instead of just &quot;dev&quot; and &quot;release&quot;, I would love to see the default be &quot;evil&quot;.<p>As in... in &quot;evil&quot; mode the compiler will abuse every rule, randomise everything that is not explicitly specified, and run your code on a virtual machine that has 19 bit ints, 23-bit pointers, bizarre memory models, or whatever to make sure that your code is <i>truly</i> robust, not just &quot;mostly robust&quot;, which is like being &quot;almost pregnant&quot;.<p>For a real life example, there was a bug lurking in the Java standard library (and several other languages!) where &quot;sort()&quot; wouldn&#x27;t work on maximum-length arrays because they used the naive (a+b)&#x2F;2 algorithm to find the mid-point of a segment and hit an integer overflow.<p>If there was an <i>evil runtime</i> with tiny integer sizes, they could have hit this with small array sizes and realised their mistake early instead of shipping broken code that blows up and crashes on the <i>biggest</i> and hence <i>most important</i> servers in the world... sometimes.<p>Taken to the n-th degree, haven&#x27;t you wondered how many similar bugs lurk in standard libraries? Which &quot;algorithms&quot; work on max-length arrays? Which only work on MAX&#x2F;2? Which on MAX&#x2F;4? Which on (MAX&#x2F;8)-53? Who knows! I don&#x27;t. You don&#x27;t either. Some or all of these could <i>blow up in your face</i> at the worst possible time and you have no way to test this[1].<p>An evil VM could be devised to test things like:<p>&quot;Throw any exception that <i>could</i> be triggered a small percentage of the time, or at command&quot;.<p>&quot;Pretend memory is far more constrained than on the specific physical host where the code is being developed.&quot;<p>&quot;Introduce network latency, UDP packet reordering, random packet drops, and every possible IO error that the host operating system might throw.&quot;<p>&quot;Use a different memory consistency model to the current physical CPU.&quot;<p>&quot;Pause threads randomly, and otherwise randomize timing and interleaving behaviour to the maximum extent allowed by the spec.&quot;<p>&quot;Simulate processors with different bitness, such as combinations of integer size vs pointer size.&quot;<p>&quot;If the spec doesn&#x27;t require any particular boolean representation, then run the code with different ones randomly. E.g.: 1, -1, and even random non-zero values for true.&quot;<p>&quot;Database queries that don&#x27;t specify the sort order are often returned reversed or randomized.&quot;<p>&quot;i18n settings that aren&#x27;t explicitly specified are randomized. Your UI language is Turkish, the keyboard is French, and the region is Japan.&quot;<p>&quot;All external environment variables are randomized and&#x2F;or substituted with similar but potentially invalid values. You must explicitly specify the whitelist of environment variables that you require to be stable.&quot;[2]<p>[1] Except for running code intended for 64-bit in 32-bit mode and testing with 2-4GB data sizes. However, there are other potential issues for which such tricks don&#x27;t work. Anyway, this is just a &quot;poor man&#x27;s evil VM&quot;. What you want is a full flexible evil VM that can constrain anything.<p>[2] Sounds like a pain in the backside for you? Now put yourself in the shoes of the poor admin that has to make this stupid thing work from a compiled binary 17 years later and has to reverse engineer the possible environment variables using a hex editor and a glass of scotch.
评论 #30985592 未加载
leros大约 3 年前
Well that explains a lot of things.
thomasfromcdnjs大约 3 年前
Pontificating a little here, but it reminds me of &quot;The road to hell is paved with good intentions&quot; quote.<p>Any external code that purports to be reusable should not be concerned with the idea of an &quot;environment&quot;.<p>Positing that reducers should be pure is fine and dandy, telling me I can&#x27;t throw in a side effect is none of your business.<p>Instead of running it twice, just make a warning log and be done with it.
评论 #30979289 未加载
评论 #30980729 未加载
评论 #30979074 未加载