Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: useRef acting weird in Strict mode. #20835

Closed
charlie1404 opened this issue Feb 17, 2021 · 5 comments
Closed

Bug: useRef acting weird in Strict mode. #20835

charlie1404 opened this issue Feb 17, 2021 · 5 comments
Labels
Resolution: Expected Behavior Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@charlie1404
Copy link

charlie1404 commented Feb 17, 2021

React version: latest (tested with 16 and 17 both)

Steps To Reproduce

Please see attached videos for reference and code sandbox for the live experiment

  1. Set component in StrictMode but wrapping it in <React.StrictMode>
  2. Have a useRef in that component that takes an empty array as input.
  3. Try mutating it on every render, maybe something like refVar.current.push("doesn't really matter what goes in here")
  4. use that array (have made a simple list from that, but should apply to all cases)
  5. array is being mutated from a different universe (to me it seems that only 😅 ).

Link to code example:
https://codesandbox.io/s/strict-bug-mrv-w7r11

The current behavior

There are 2 console.log to show the value of the array before and after array mutation.
In strict mode when clicked provided button array gets an extra element, same as pushed valued. (Please see attachment one)

The expected behavior

I believe this should be the same as when not in not strict mode.

Apart from this I also have tried using the debugger to see what actually is happening. When added breakpoint to list.current.push() it seems dev tools is stopping on that line twice. What even more confusing to me is, if in case function ran(rendered) twice, how come there is console only once, please attached video (attachment two ) for the same.

Attachments:

  1. https://user-images.githubusercontent.com/20264337/108258484-12ce5300-7186-11eb-8bb2-6e82a14ac856.mov
  2. https://user-images.githubusercontent.com/20264337/108256943-1fea4280-7184-11eb-9840-2dfc243eb6ae.mov
@charlie1404 charlie1404 added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Feb 17, 2021
@eps1lon
Copy link
Collaborator

eps1lon commented Feb 17, 2021

Thanks for the report.

That is definitely a common confusion. In case you're not aware of what StrictMode does and why it is used: StrictMode warns about various problematic patterns.

One of which is having methods with side-effects that shouldn't have side-effects in React. Mutating a ref is such a side-effect and doing it when rendering a component is problematic. StrictMode calls the render method twice to help detect these problems.

The unfortunate part is that you've also hit another "quirk" of StrictMode (which only applies to React 17): Calls to console methods during the second render call (by StrictMode) are ignored. There are plans to enable double-logging in StrictMode. If you're interested in these, please upvote #19710.

I hope this clears up any confusion about the observed behavior. Feel free to ask further questions if some explanations are unclear.

@bvaughn
Copy link
Contributor

bvaughn commented Feb 17, 2021

Try mutating it on every render

As @eps1lon mentioned, mutation during render is specifically something React does not support and StrictMode exists to help flush out cases of this. 😄

I'm going to go ahead and close this issue since everything seems to be working as designed. We can talk more if you still have questions or concerns though! 👍

@bvaughn bvaughn closed this as completed Feb 17, 2021
@charlie1404
Copy link
Author

@eps1lon @bvaughn Thanks for the explanation, I think I got it.
Yes I was aware that we should not do mutations in render but was not aware of render being called twice in strict mode 😅

The bigger source of confusion was that console's are being silent. Not sure but to me this behavior by default seems not beginner-friendly.

my use case was to count the number of renders and show them on UI (nothing real but an experiment), which I ended up doing using useEffect without dependency array.

@bvaughn
Copy link
Contributor

bvaughn commented Feb 18, 2021

The bigger source of confusion was that console's are being silent. Not sure but to me this behavior by default seems not beginner-friendly.

Yeah, this is a feature that has pros and cons that have been debated at length (on other issues and within the React team) without a clear solution. We chose the default we thought was best but it's not perfect. In the future we plan to add some extra tools to DevTools to help with discoverability (and maybe to allow you to override the default) FWIW.

@gaearon
Copy link
Collaborator

gaearon commented Mar 30, 2022

To follow up on this, we've changed the logging behavior in 18 to be more intuitive.
#21783 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Expected Behavior Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

4 participants