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

Fix: make v5 Router compatible with v18 StrictMode #8831

Merged
merged 2 commits into from May 9, 2022

Conversation

jgoz
Copy link

@jgoz jgoz commented May 1, 2022

Fixes #7870.

In React 18, Strict Mode attempts to detect unexpected side effects that might happen when rendering in concurrent mode. For class components, it intentionally double-invokes the constructor, render(), and shouldComponentUpdate(). It also double-invokes both layout and passive effects by mounting, unmounting, and then remounting.

Router in v5 was not compatible with this primarily because the main history subscription was created in the component constructor. Here is a simplified outline of the component lifecycle in StrictMode in v5.3.1:

  • constructor — listen (this instance is not used)
  • constructor — listen
  • render
  • render
  • componentDidMount
  • componentWillUnmount — unlisten(!)
  • componentDidMount

At this point, there were no history subscriptions, so setState was never being invoked.

The fix presented in this PR moves the main history subscription into componentDidMount to make it resilient to unmount/remount cycles. Here is the new simplified outline as of this PR:

  • constructor — listen (this instance is not used)
  • constructor — listen
  • render
  • render
  • componentDidMount — unlisten, listen
  • componentWillUnmount — unlisten
  • componentDidMount — listen

The listener in the constructor is only used for detecting redirects caused by child mounts and the subscription is only active until componentDidMount, at which point it is disposed and replaced with the main listener. Since the main listener is attached in componentDidMount, it will be recreated if the component is unmounted and then remounted without being fully reconstructed.

Tests

Rather than changing the local react dependency to v18, I added synthetic tests that simulate the new StrictMode behavior. If the maintainers would prefer to see tests using actual rendering in v18, I'd be happy to amend this.

@levibuzolic
Copy link

levibuzolic commented May 2, 2022

Just tested these changes on a large app at the moment and it looks to be working great. 👏

I've still got one small test case that's broken, but I suspect it's not actually relevant and probably pointing to a bug in our own codebase. Was a bug in our code.

@jgoz
Copy link
Author

jgoz commented May 7, 2022

@timdorr 👋 friendly ping. Any thoughts on the approach I took here?

@timdorr
Copy link
Member

timdorr commented May 9, 2022

I think this looks good. I'll merge it in and see if we can get this pushed in the next few days.

@timdorr timdorr merged commit a68510f into remix-run:v5 May 9, 2022
@jgoz jgoz deleted the 7870-fix-strict-mode-react-18 branch May 9, 2022 16:57
@d-pollard
Copy link

@timdorr any way we could get this in today?

@timdorr
Copy link
Member

timdorr commented May 12, 2022

I'm dealing with a burst water line in my house, so I've been derailed a bit. I'm still planning on releasing this, though! Sorry for the delay in my end.

@d-pollard
Copy link

@timdorr no worries! Good luck with your burst water line, hope it gets fixed fast!

@timdorr
Copy link
Member

timdorr commented May 17, 2022

OK, got it published now!

@francois-codes
Copy link

francois-codes commented May 18, 2022

@timdorr looks like something went wrong when publishing this.
I see in the package.json of react-router-native that it has react-router: "2" as dependency.
This is crashing our apps as react-router@2 is trying to call React.PropTypes which no longer exists.

our work around was to add a resolution to force react-router >= 3.0.0 but it is likely that this version may cause issues

this is the problematic bit:

@timdorr
Copy link
Member

timdorr commented May 19, 2022

Just fixed that in 5.3.3 😵

@ajtgt
Copy link

ajtgt commented Jun 1, 2022

Just fixed that in 5.3.3 😵

Thanks

kodiakhq bot pushed a commit to sullivanpj/open-system that referenced this pull request Jun 26, 2023
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [react-router](https://togithub.com/remix-run/react-router) | [`5.2.0` -> `5.3.4`](https://renovatebot.com/diffs/npm/react-router/5.2.0/5.3.4) | [![age](https://badges.renovateapi.com/packages/npm/react-router/5.3.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/react-router/5.3.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/react-router/5.3.4/compatibility-slim/5.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/react-router/5.3.4/confidence-slim/5.2.0)](https://docs.renovatebot.com/merge-confidence/) |
| [react-router-dom](https://togithub.com/remix-run/react-router) | [`5.2.0` -> `5.3.4`](https://renovatebot.com/diffs/npm/react-router-dom/5.2.0/5.3.4) | [![age](https://badges.renovateapi.com/packages/npm/react-router-dom/5.3.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/react-router-dom/5.3.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/react-router-dom/5.3.4/compatibility-slim/5.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/react-router-dom/5.3.4/confidence-slim/5.2.0)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>remix-run/react-router (react-router)</summary>

### [`v5.3.4`](https://togithub.com/remix-run/react-router/releases/tag/v5.3.4)

[Compare Source](https://togithub.com/remix-run/react-router/compare/v5.3.3...v5.3.4)

We removed the `mini-create-react-context` dependency, moving it into an internal module to eliminate peer dependency warnings for users on React 18 ([#&#8203;9382](https://togithub.com/remix-run/react-router/issues/9382)).

**Full Changelog**: remix-run/react-router@v5.3.3...v5.3.4

### [`v5.3.3`](https://togithub.com/remix-run/react-router/releases/tag/v5.3.3)

[Compare Source](https://togithub.com/remix-run/react-router/compare/v5.3.2...v5.3.3)

This release fixes a bad version selector in react-router-native.

### [`v5.3.2`](https://togithub.com/remix-run/react-router/releases/tag/v5.3.2)

[Compare Source](https://togithub.com/remix-run/react-router/compare/v5.3.1...v5.3.2)

-   Fix: make v5 Router compatible with v18 StrictMode by [@&#8203;jgoz](https://togithub.com/jgoz) in [remix-run/react-router#8831

### [`v5.3.1`](https://togithub.com/remix-run/react-router/releases/tag/v5.3.1)

[Compare Source](https://togithub.com/remix-run/react-router/compare/v5.2.1...v5.3.1)

This release adds missing `LICENSE` files to the published build.

### [`v5.2.1`](https://togithub.com/remix-run/react-router/releases/tag/v5.2.1)

[Compare Source](https://togithub.com/remix-run/react-router/compare/v5.2.0...v5.2.1)

This release fixes a bug with `<Link>` so that, when the `to` location is the same as the current, the history state entry is replaced instead of pushed to the stack. See [remix-run/react-router#5362 for details. 🥳

Thanks to [@&#8203;guidobouman](https://togithub.com/guidobouman) for the PR and for everyone else who weighed in for the fix!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/sullivanpj/open-system).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants