Bug: React 18 Strict mode does not simulate unsetting and re-setting refs
  1. Use <React.StrictMode>
  2. Set a ref to a JSX element in a component
  3. Create a useLayoutEffect/useEffect in the component where the returned cleanup function console logs the ref
  4. Save and refresh the app
  5. You should have access to the ref element in the the useLayoutEffect/useEffect cleanup function during the simulated unmount.

Link to code example: https://codesandbox.io/s/proud-snow-ox4ngx?file=/src/App.js

The current behavior

Does not unset/re-set refs in simulated unmount. This could lead to unexpected bugs in development like having double-set event listeners, i.e.if( ref.current ){ //add eventlistener to it }and might not match the behavior of actually unmounting the DOM node as described in the docs: https://reactjs.org/docs/strict-mode.html

On the second mount, React will restore the state from the first mount. This feature simulates user behavior such as a user tabbing away from a screen and back, ensuring that code will properly handle state restoration.

The expected behavior

In normal unmounts and mounts refs are unset(before layout effects are cleaned up) and set(before layout effects).

 

I confirm. In my case, this causes a nasty bug. Everything related refs that worked in version 17 just stopped working in version 18 without any error messages. I definitely can't use React.StrictMode right now.

Moreover, during the first installation using create-react-app, a person will not be able to use any library that uses the refs functionality, thinking that the library does not work. My suggestion is to remove React.StrictMode from default create-react-app set up until the bug is fixed.

 

According to this post:

Whether a component gets hidden or unmounted, refs that are attached to host components (like HTML elements) will be cleaned up and re-initialized the same as they are today during unmount/remount.

Refs that store use-managed values won't be reset when a component is hidden though. They allow things to be persisted for the case where a component is hidden and later shown again.

It makes sense to keep the user-managed values around as they are part of the component state that will be restored, however refs to DOM elements maybe should not be set?