Skip to content

Commit ebf912b

Browse files
pshrmnCompuIves
authored andcommitted
Correctly update history for pop and replace actions (codesandbox#1158)
<!-- Please make sure you are familiar with and follow the instructions in the contributing guidelines (found in the CONTRIBUTING.md file). Please fill out the information below to expedite the review and (hopefully) merge of your pull request! --> <!-- Is it a Bug fix, feature, docs update, ... --> **What kind of change does this PR introduce?** This alters how the fake browser (`<Preview>`) manages its `history` state. Fixes codesandbox#1102. <!-- You can also link to an open issue here --> **What is the current behavior?** Previously, all `urlchange` dispatches were treated as pushes (append URL to end of `history.state` and increment `state.historyPosition`). The fake browser's back and forward buttons got around this by manually updating the state, but manual `history.go()` and `history.replaceState()` calls resulted in an incorrect history array/position. This behavior can be seen here: https://codesandbox.io/s/vqw1mnnl9y (steps to reproduce are described in codesandbox#1102) <!-- if this is a feature change --> **What is the new behavior?** When `history.go()` is called, the `state.history` array is unchanged while the `state.historyPosition` is altered by the go amount. When `history.replaceState()` is called, the `state.history` array is altered to replace the current entry at `state.historyPosition` with the new URL. `BasePreview.handleForward()` and `BasePreview.handleBack()` no longer manually set state because they can rely on `commitUrl()` to handle this correctly. <!-- Have you done all of these things? --> **Checklist**: <!-- add "N/A" to the end of each line that's irrelevant to your changes --> <!-- to check an item, place an "x" in the box like so: "- [x] Documentation" --> - [ ] Documentation (N/A?) - [ ] Tests (would probably be nice, but I'm not sure if there is a way to test this) - [x] Ready to be merged <!-- In your opinion, is this ready to be merged as soon as it's reviewed? --> - [ ] Added myself to contributors table (already in there) <!-- this is optional, see the contributing guidelines for instructions --> <!-- feel free to add additional comments --> <!-- Thank you for contributing! -->
1 parent 791979c commit ebf912b

File tree

2 files changed

+37
-31
lines changed

2 files changed

+37
-31
lines changed

packages/app/src/app/components/Preview/index.js

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ class BasePreview extends React.Component<Props, State> {
385385
break;
386386
}
387387
case 'urlchange': {
388-
this.commitUrl(data.url);
388+
this.commitUrl(data.url, data.action, data.diff);
389389
break;
390390
}
391391
case 'resize': {
@@ -557,37 +557,43 @@ class BasePreview extends React.Component<Props, State> {
557557
dispatch({
558558
type: 'urlback',
559559
});
560-
561-
const { historyPosition, history } = this.state;
562-
this.setState({
563-
historyPosition: this.state.historyPosition - 1,
564-
urlInAddressBar: history[historyPosition - 1],
565-
});
566560
};
567561

568562
handleForward = () => {
569563
dispatch({
570564
type: 'urlforward',
571565
});
572-
573-
const { historyPosition, history } = this.state;
574-
this.setState({
575-
historyPosition: this.state.historyPosition + 1,
576-
urlInAddressBar: history[historyPosition + 1],
577-
});
578566
};
579567

580-
commitUrl = (url: string) => {
568+
commitUrl = (url: string, action: string, diff: number) => {
581569
const { history, historyPosition } = this.state;
582570

583-
const currentHistory = history[historyPosition] || '';
584-
if (currentHistory !== url) {
585-
history.length = historyPosition + 1;
586-
this.setState({
587-
history: [...history, url],
588-
historyPosition: historyPosition + 1,
589-
urlInAddressBar: url,
590-
});
571+
switch (action) {
572+
case 'POP':
573+
this.setState(prevState => {
574+
const newPosition = prevState.historyPosition + diff;
575+
return {
576+
historyPosition: newPosition,
577+
urlInAddressBar: url,
578+
};
579+
});
580+
break;
581+
case 'REPLACE':
582+
this.setState(prevState => ({
583+
history: [
584+
...prevState.history.slice(0, historyPosition),
585+
url,
586+
...prevState.history.slice(historyPosition + 1),
587+
],
588+
urlInAddressBar: url,
589+
}));
590+
break;
591+
default:
592+
this.setState({
593+
history: [...history, url],
594+
historyPosition: historyPosition + 1,
595+
urlInAddressBar: url,
596+
});
591597
}
592598
};
593599

packages/sandbox-hooks/url-listeners.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { dispatch, isStandalone, listen } from 'codesandbox-api';
22

3-
function sendUrlChange(url: string) {
3+
function sendUrlChange(url: string, action?: string, diff?: number) {
44
dispatch({
55
type: 'urlchange',
66
url,
7+
diff,
8+
action,
79
});
810
}
911

@@ -15,11 +17,9 @@ let historyPosition = -1;
1517
let disableNextHashChange = false;
1618

1719
function pushHistory(url, state) {
18-
if (historyPosition === -1 || historyList[historyPosition].url !== url) {
19-
historyPosition += 1;
20-
historyList.length = historyPosition + 1;
21-
historyList[historyPosition] = { url, state };
22-
}
20+
historyPosition += 1;
21+
historyList.length = historyPosition + 1;
22+
historyList[historyPosition] = { url, state };
2323
}
2424

2525
function pathWithHash(location) {
@@ -48,7 +48,7 @@ export default function setupHistoryListeners() {
4848
const oldURL = document.location.href;
4949
origHistoryProto.replaceState.call(window.history, state, '', url);
5050
const newURL = document.location.href;
51-
sendUrlChange(newURL);
51+
sendUrlChange(newURL, 'POP', delta);
5252
if (newURL.indexOf('#') === -1) {
5353
window.dispatchEvent(new PopStateEvent('popstate', { state }));
5454
} else {
@@ -77,7 +77,7 @@ export default function setupHistoryListeners() {
7777
replaceState(state, title, url) {
7878
origHistoryProto.replaceState.call(window.history, state, title, url);
7979
historyList[historyPosition] = { state, url };
80-
sendUrlChange(document.location.href);
80+
sendUrlChange(document.location.href, 'REPLACE');
8181
},
8282
});
8383

@@ -137,7 +137,7 @@ export default function setupHistoryListeners() {
137137
pushHistory(pathWithHash(document.location), null);
138138

139139
setTimeout(() => {
140-
sendUrlChange(document.location.href);
140+
sendUrlChange(document.location.href, 'REPLACE');
141141
});
142142
}
143143
return listen(handleMessage);

0 commit comments

Comments
 (0)