Skip to content

Commit

Permalink
reduce internal states in useBlocker
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandojbf committed Jun 30, 2023
1 parent 499af9a commit c2e2ac1
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/hungry-ladybugs-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-router": patch
---

reduce number of internal state in useBlocker
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
- emzoumpo
- engpetermwangi
- ericschn
- fernandojbf
- FilipJirsak
- frontsideair
- fyzhu
Expand Down
31 changes: 10 additions & 21 deletions packages/react-router/lib/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -935,10 +935,10 @@ let blockerId = 0;
* cross-origin navigations.
*/
export function useBlocker(shouldBlock: boolean | BlockerFunction): Blocker {
let blockerKey = React.useMemo(() => String(++blockerId), []);
let { router, basename } = useDataRouterContext(DataRouterHook.UseBlocker);
let state = useDataRouterState(DataRouterStateHook.UseBlocker);

let [blockerKey, setBlockerKey] = React.useState("");
let blockerFunction = React.useCallback<BlockerFunction>(
(arg) => {
if (typeof shouldBlock !== "function") {
Expand Down Expand Up @@ -971,29 +971,18 @@ export function useBlocker(shouldBlock: boolean | BlockerFunction): Blocker {
[basename, shouldBlock]
);

// This effect is in charge of blocker key assignment and deletion (which is
// tightly coupled to the key)
// register router blocker using blocker unique key
React.useEffect(() => {
let key = String(++blockerId);
setBlockerKey(key);
return () => router.deleteBlocker(key);
}, [router]);

// This effect handles assigning the blockerFunction. This is to handle
// unstable blocker function identities, and happens only after the prior
// effect so we don't get an orphaned blockerFunction in the router with a
// key of "". Until then we just have the IDLE_BLOCKER.
React.useEffect(() => {
if (blockerKey !== "") {
router.getBlocker(blockerKey, blockerFunction);
}
router.getBlocker(blockerKey, blockerFunction);
}, [router, blockerKey, blockerFunction]);

// Prefer the blocker from `state` not `router.state` since DataRouterContext
// is memoized so this ensures we update on blocker state updates
return blockerKey && state.blockers.has(blockerKey)
? state.blockers.get(blockerKey)!
: IDLE_BLOCKER;
// unregister only on unmount to not loose state
React.useEffect(() => {
return () => router.deleteBlocker(blockerKey);
}, [router, blockerKey]);

// If key blocker does not exist should be IDLE
return state.blockers.get(blockerKey) || IDLE_BLOCKER;
}

/**
Expand Down

0 comments on commit c2e2ac1

Please sign in to comment.