Skip to content

Commit 588316f

Browse files
committed
Fix popstate to remove unused event listener
1 parent 0e67d2e commit 588316f

File tree

3 files changed

+40
-47
lines changed

3 files changed

+40
-47
lines changed

src/backend/controllers/timeJump.ts

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,40 @@ const circularComponentTable = new Set();
1919
*
2020
*/
2121
export default function timeJump(mode: Status) {
22-
// payload from index.ts is assigned to target
2322
/**
24-
* @param target - The target snapshot to re-render
23+
* The target snapshot to re-render
24+
*/
25+
let target;
26+
/**
27+
* This function is to aid the removeListener for 'popstate'
28+
*/
29+
// IMPORTANT: DO NOT move this function into return function. This function is out here so that it will not be redefined any time the return function is invoked. This is importatnt for removeEventListener for popstate to work.
30+
const popStateHandler = () => {
31+
initiateJump(target, mode);
32+
};
33+
34+
/**
35+
* @param inputTarget - The target snapshot to re-render. The payload from index.ts is assigned to inputTarget
2536
* @param firstCall - A boolean flag checking for `firstCall`
2637
*/
27-
return (target: Tree, firstCall = false): void => {
38+
return (inputTarget: Tree, firstCall = false): void => {
2839
// Setting mode disables setState from posting messages to window
2940
mode.jumping = true;
41+
// Set target for popStateHandler usage:
42+
target = inputTarget;
3043
// Clearn the circularComponentTable
3144
if (firstCall) circularComponentTable.clear();
32-
// Determine if user is navigating to another site
33-
const navigating: boolean = routes.navigate(target.route);
34-
45+
// Determine if user is navigating to another route
46+
// NOTE: Inside routes.navigate, if user is navigating, we will invoke history.go, which will go back/forth based on # of delta steps. This will trigger a popstate event. Since history.go is an async method, the event listener is the only way to invoke timeJump after we have arrived at the desirable route.
47+
const navigating: boolean = routes.navigate(inputTarget.route);
3548
if (navigating) {
36-
// Initiate popStateHandler to aid the removeListener for 'popstate'
37-
const popStateHandler = () => {
38-
initiateJump(target, mode);
39-
};
40-
// removeEventListener('popstate', popStateHandler);
41-
// Background will "perform" popstate till get to the correct history location?
49+
// Remove 'popstate' listener to avoid duplicate listeners
50+
removeEventListener('popstate', popStateHandler);
51+
// To invoke initateJump after history.go is complete
4252
addEventListener('popstate', popStateHandler);
4353
} else {
44-
// Intiate the jump
45-
initiateJump(target, mode);
54+
// Intiate the jump immideately if not navigating
55+
initiateJump(inputTarget, mode);
4656
}
4757
};
4858
}
@@ -53,7 +63,6 @@ export default function timeJump(mode: Status) {
5363
* @param mode - The current mode (i.e. jumping, time-traveling, or paused)
5464
*/
5565
async function initiateJump(target, mode): Promise<void> {
56-
console.log('JUMP');
5766
updateTreeState(target).then(() => {
5867
document.body.onmouseover = () => {
5968
mode.jumping = false;
@@ -84,48 +93,34 @@ async function updateTreeState(target): Promise<void> {
8493
// Destructure component data:
8594
const { index, state, hooksIndex, hooksState } = target.componentData;
8695
// ------------------------STATEFUL CLASS COMPONENT-------------------------
87-
// for stateful class components
88-
// check if it is a stateful class component
89-
// if yes, find the component by its index and assign it to a variable
90-
// call that components setState method to reset state to the state at the time of the jump snapshot
91-
//index can be zero => falsy value => DO NOT REMOVE UNDEFINED
96+
// Check if it is a stateful class component
97+
// Index can be zero => falsy value => DO NOT REMOVE UNDEFINED
9298
if (index !== undefined) {
93-
// Obtain component data & its update method at the given index
99+
// Obtain the BOUND update method at the given index
94100
const classComponent = componentActionsRecord.getComponentByIndex(index);
95-
// If the user navigate to another page during jumps, Routes methods will popState until find a match => this cause changes in componentActionRecord => keep the if statement, otherwise will run into Uncaught Promise type error.
96-
if (classComponent?.setState) {
97-
// Update component state
98-
await classComponent.setState(
99-
// prevState contains the states of the snapshots we are jumping FROM, not jumping TO
100-
(prevState) => state,
101-
);
102-
}
103-
// Else statement is to ensure if a mismatch, this popstate is not the correct componentActionRecord. Return immediately to avoid traverse the entire tree
104-
else return;
105-
101+
// Update component state
102+
await classComponent.setState(
103+
// prevState contains the states of the snapshots we are jumping FROM, not jumping TO
104+
(prevState) => state,
105+
);
106106
// Iterate through new children after state has been set
107107
target.children.forEach((child) => updateTreeState(child));
108108
return;
109109
}
110110

111111
// ----------------------STATEFUL FUNCTIONAL COMPONENT----------------------
112-
// check if component states are set with hooks
112+
// Check if it is a stateful functional component
113113
// if yes, grab all relevant components for this snapshot by its index
114114
// call dispatch on each component passing in the corresponding currState value
115115
//index can be zero => falsy value => DO NOT REMOVE UNDEFINED
116116
if (hooksIndex !== undefined) {
117-
// Obtain component data & its update method at the given index
117+
// Obtain the array of BOUND update methods at the given indexes.
118+
// NOTE: each useState will be a separate update method. So if a component have 3 useState, we will obtain an array of 3 update methods.
118119
const functionalComponent = componentActionsRecord.getComponentByIndexHooks(hooksIndex);
119-
// If the user navigate to another page during jumps, Routes methods will popState until find a match => this cause changes in componentActionRecord => keep the if statement, otherwise will run into Uncaught Promise type error.
120-
if (functionalComponent[0]?.dispatch) {
121-
// Update component state
122-
for (let i in functionalComponent) {
123-
await functionalComponent[i].dispatch(Object.values(hooksState)[i]);
124-
}
120+
// Update component state
121+
for (let i in functionalComponent) {
122+
await functionalComponent[i].dispatch(Object.values(hooksState)[i]);
125123
}
126-
// Else statement is to ensure if a mismatch, this popstate is not the correct componentActionRecord. Return immediately to avoid traverse the entire tree
127-
else return;
128-
129124
// Iterate through new children after state has been set
130125
target.children.forEach((child) => updateTreeState(child));
131126
return;

src/backend/models/routes.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable max-classes-per-file */
22
/* eslint-disable max-len */
3-
3+
import componentActionsRecord from './masterState';
44
/**
55
* @class Route instances are created by the addRoute method on Routes. A Route instance has two properties: the url of the route and a unique id.
66
*/
@@ -93,7 +93,6 @@ class Routes {
9393
*/
9494
navigate(route: Route): boolean {
9595
let targetIndex: number | undefined;
96-
9796
// Loop through the routeHistory stack
9897
for (let i = 0; i < this.routeHistory.length; i += 1) {
9998
// If within the route history, found a match of url & id from the passed in route, update `targetIndex`
@@ -116,7 +115,6 @@ class Routes {
116115
// if delta != 0 => need to navigate to another page
117116
if (delta !== 0) {
118117
// Navigate to that page based on delta steps
119-
console.log({ delta });
120118
window.history.go(delta);
121119
return true;
122120
}

src/backend/routers/snapShot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Snapshot, Status, FiberRoot } from '../types/backendTypes';
22
// passes the data down to its components
33
import componentActionsRecord from '../models/masterState';
44
import routes from '../models/routes';
5-
import createTree from '../controllers/createTree/CreateTree';
5+
import createTree from '../controllers/createTree/createTree';
66

77
// ---------------------------UPDATE TREE SNAP SHOT-----------------------------
88
/**

0 commit comments

Comments
 (0)