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

@remix-run/router: Add support for navigation blocking #9709

Merged
merged 54 commits into from Jan 13, 2023
Merged

Conversation

chaance
Copy link
Collaborator

@chaance chaance commented Dec 8, 2022

This PR adds support for low-level blocking of navigations within the app's location origin via unstable_useBlocker. We are confident in this approach but wanted to initially release it under a flag to give users an opportunity to test and provide feedback.

In addition, I added an options parameter to useBeforeUnload so that users can have more control over how that event listener behaves when dealing with cross-origin navigations.

Closes #8139.

@changeset-bot
Copy link

changeset-bot bot commented Dec 8, 2022

🦋 Changeset detected

Latest commit: 7749172

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
react-router-dom Minor
@remix-run/router Minor
react-router Minor
react-router-dom-v5-compat Minor
react-router-native Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

/.env
/NOTES.md
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed somewhere to keep notes because this was getting confusing 😅

@chaance chaance marked this pull request as draft December 8, 2022 21:23
Copy link
Contributor

@brophdawg11 brophdawg11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good!

packages/router/__tests__/blocking-test.ts Outdated Show resolved Hide resolved
packages/router/history.ts Show resolved Hide resolved
packages/router/history.ts Show resolved Hide resolved
packages/router/router.ts Outdated Show resolved Hide resolved
packages/router/router.ts Outdated Show resolved Hide resolved
@brophdawg11 brophdawg11 changed the base branch from dev to release-next January 13, 2023 19:20
@brophdawg11 brophdawg11 changed the base branch from release-next to dev January 13, 2023 19:20
return (
<>
<p style={{ color: "red" }}>
Blocked the last navigation to {blocker.location.pathname}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this to a separate component so this wouldn't blow up on blocker.location.pathname when in an unblocked state. everything got evaluated in the above key lookup approach.

if (listener) {
index = nextIndex;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should always be updating this even if no one is listening - never showed up as an issue since we always have a listener

Comment on lines 1115 to 1123
// Short circuit if navigation is blocked
if (
Array.from(state.blockers).some(([_, blocker]) => {
return blocker.state === "blocked";
})
) {
return;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think his is leftover form very early. Our entry points are popstate and router.navigate so we can just check for blocking there

Copy link
Contributor

@brophdawg11 brophdawg11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// case we should log a warning as it will result in bugs.
if (index == null) {
index = 0;
globalHistory.replaceState({ ...globalHistory.state, idx: index }, "");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This replaceState() line is causing a new regression for my project when testing with Jest and JSDom. I observed the following series of circumstances:

  1. The test runs in React strict mode, causing the React Router to mount twice.

  2. When the React Router is loaded the 1st time, window.location.href is http://www.example.com/path/to/route

  3. When the React Router is loaded the 1st time, index is null.

  4. The replaceState changes window.location.href to http://localhost/. Notice both the origin and the path has changed.

  5. When the React Router is loaded the 2nd time (strict mode), the URL is now wrong, causing the wrong route to load and my test to fail.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose the following which fixes my problem: #10001

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants