Skip to content

Commit 652943d

Browse files
committed
Preparing for React 18: change how router decides to PUSH new URL
With React 18, the old hack of setting a boolean during the browser-based update doesn't work anymore (for some reason)and a state update comes in after we think the browser is done. This causes the history stack to be destroyed so we can't go to the help page, back, then forward again. We now check to see if the Redux-driven URL would result in us ending back at the same URL the browser does, and if so we just ignore the update.
1 parent 6cb6f8b commit 652943d

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

ui/frontend/uss-router/index.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,28 @@ export function createRouter<St, SubSt, A extends Action<any>>({
3030
stateToLocation,
3131
locationToAction,
3232
}: CreateRouterArg<St, SubSt, A>): RouterObject {
33-
let doingUpdateFromBrowser = false; // Avoid immediately PUSHing the state again
3433
let interestingPrevState: SubSt;
3534

3635
// Watch changes to the Redux state
3736
store.subscribe(() => {
38-
if (doingUpdateFromBrowser) { return; }
39-
4037
const nextState = store.getState();
41-
const interestingNextState = stateSelector(nextState);
42-
43-
if (!isEqual(interestingNextState, interestingPrevState)) {
44-
const nextLocation = stateToLocation(nextState);
4538

46-
history.push(nextLocation);
39+
// It's only worth checking if our state subset has changed.
40+
const interestingNextState = stateSelector(nextState);
41+
if (isEqual(interestingNextState, interestingPrevState)) { return; }
42+
interestingPrevState = interestingNextState;
4743

48-
interestingPrevState = interestingNextState;
49-
}
44+
// If our next location matches where we already are, leave the
45+
// history stack as-is.
46+
const nextLocation = stateToLocation(nextState);
47+
if (pathsEqualEnough(history, history.location, nextLocation)) { return; }
48+
history.push(nextLocation);
5049
});
5150

5251
const dispatchBrowserLocationChange = (nextLocation: Location) => {
5352
const action = locationToAction(nextLocation);
5453
if (action) {
55-
doingUpdateFromBrowser = true;
5654
store.dispatch(action);
57-
doingUpdateFromBrowser = false;
5855
}
5956
};
6057

@@ -68,10 +65,6 @@ export function createRouter<St, SubSt, A extends Action<any>>({
6865
// Load initial browser state
6966
dispatchBrowserLocationChange(history.location);
7067

71-
// Now that we've set up any initial state, we keep it so we can
72-
// tell when the location needs to change.
73-
interestingPrevState = stateSelector(store.getState());
74-
7568
return {
7669
provisionalLocation: (makeAction: () => A) => {
7770
const state = store.getState();
@@ -85,3 +78,10 @@ export function createRouter<St, SubSt, A extends Action<any>>({
8578
},
8679
};
8780
}
81+
82+
function pathsEqualEnough(history: BrowserHistory, a: Partial<Path>, b: Partial<Path>): boolean {
83+
const aHref = history.createHref(a);
84+
const bHref = history.createHref(b);
85+
86+
return aHref === bHref;
87+
}

0 commit comments

Comments
 (0)