Skip to content

Commit 36c6ef3

Browse files
committed
added more reducer info in reducer state
1 parent ff0e102 commit 36c6ef3

File tree

4 files changed

+107
-60
lines changed

4 files changed

+107
-60
lines changed

src/backend/controllers/createTree.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -207,30 +207,34 @@ export default function createTree(currentFiberNode: Fiber): Tree {
207207
if (memoizedState.queue) {
208208
try {
209209
const hooksStates = getHooksStateAndUpdateMethod(memoizedState);
210-
console.log('hook states', hooksStates);
211-
// Get the hooks names by parsing the elementType
212210
const hooksNames = getHooksNames(elementType.toString());
213-
// Intialize state & index:
211+
214212
componentData.hooksState = {};
215-
componentData.reducerState = null;
213+
componentData.reducerStates = []; // New array to store reducer states
216214
componentData.hooksIndex = [];
217215

218-
hooksStates.forEach(({ state, component, isReducer }, i) => {
216+
hooksStates.forEach(({ state, component, isReducer, lastAction, reducer }, i) => {
219217
componentData.hooksIndex.push(componentActionsRecord.saveNew(component));
220218

221219
if (isReducer) {
222-
// If it's a reducer, store its state
223-
componentData.reducerState = state;
220+
// Store reducer-specific information
221+
componentData.reducerStates.push({
222+
state,
223+
lastAction,
224+
reducerIndex: i,
225+
hookName: hooksNames[i]?.varName || `Reducer: ${i}`,
226+
});
227+
} else {
228+
// Regular useState hook
229+
componentData.hooksState[hooksNames[i]?.varName || `State: ${i}`] = state;
224230
}
225-
// Otherwise treat as useState
226-
componentData.hooksState[hooksNames[i]?.varName || `Reducer: ${i}`] = state;
227231
});
228-
229-
// Pass to front end
230-
newState = componentData.hooksState;
231-
console.log('new state', newState);
232+
newState = {
233+
...componentData.hooksState,
234+
reducers: componentData.reducerStates,
235+
};
232236
} catch (err) {
233-
console.log('Error extracting functional component state:', {
237+
console.log('Error extracting component state:', {
234238
componentName,
235239
memoizedState,
236240
error: err,

src/backend/controllers/statePropExtractors.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,30 @@ export function getHooksStateAndUpdateMethod(
6969
): Array<HookStateItem> {
7070
const hooksStates: Array<HookStateItem> = [];
7171
while (memoizedState) {
72-
// Check for useReducer hook
73-
if (
74-
memoizedState.queue &&
75-
memoizedState.memoizedState &&
76-
memoizedState.queue.lastRenderedReducer.name !== 'basicStateReducer' // only present in useState
77-
) {
78-
hooksStates.push({
79-
component: memoizedState.queue,
80-
state: memoizedState.memoizedState,
81-
isReducer: true,
82-
});
83-
} else if (memoizedState.queue) {
84-
hooksStates.push({
85-
component: memoizedState.queue,
86-
state: memoizedState.memoizedState,
87-
});
72+
if (memoizedState.queue) {
73+
// Check if this is a reducer hook by looking at the lastRenderedReducer
74+
const isReducer = memoizedState.queue.lastRenderedReducer?.name !== 'basicStateReducer';
75+
76+
if (isReducer) {
77+
// For useReducer hooks, we want to store:
78+
// 1. The current state
79+
// 2. The last action that was dispatched (if available)
80+
// 3. The reducer function itself
81+
hooksStates.push({
82+
component: memoizedState.queue,
83+
state: memoizedState.memoizedState,
84+
isReducer: true,
85+
lastAction: memoizedState.queue.lastRenderedAction || null,
86+
reducer: memoizedState.queue.lastRenderedReducer || null,
87+
});
88+
} else {
89+
// Regular useState hook
90+
hooksStates.push({
91+
component: memoizedState.queue,
92+
state: memoizedState.memoizedState,
93+
isReducer: false,
94+
});
95+
}
8896
}
8997
memoizedState = memoizedState.next;
9098
}

src/backend/controllers/timeJump.ts

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export default function timeJumpInitiation(mode: Status) {
2424
* @param targetSnapshot - The target snapshot to re-render. The payload from index.ts is assigned to targetSnapshot
2525
*/
2626
return async function timeJump(targetSnapshot: Tree): Promise<void> {
27-
console.log('Time jump initiated with targetSnapshot:', targetSnapshot); // logging to see if the re-rendering bug lives here
2827
mode.jumping = true;
2928
// Reset mode.navigating
3029
delete mode.navigating;
@@ -50,21 +49,25 @@ async function updateReactFiberTree(
5049
circularComponentTable: Set<any> = new Set(),
5150
): Promise<void> {
5251
if (!targetSnapshot) return;
53-
// Base Case: if has visited, return
54-
if (circularComponentTable.has(targetSnapshot)) {
55-
return;
56-
} else {
57-
circularComponentTable.add(targetSnapshot);
58-
}
59-
// ------------------------STATELESS/ROOT COMPONENT-------------------------
52+
if (circularComponentTable.has(targetSnapshot)) return;
53+
54+
circularComponentTable.add(targetSnapshot);
55+
6056
if (targetSnapshot.state === 'stateless' || targetSnapshot.state === 'root') {
6157
targetSnapshot.children.forEach((child) => updateReactFiberTree(child, circularComponentTable));
6258
return;
6359
}
6460

65-
const { index, state, hooksIndex, hooksState, reducerState } = targetSnapshot.componentData;
61+
const { index, state, hooksIndex, hooksState, reducerStates } = targetSnapshot.componentData;
62+
63+
console.log('Processing snapshot in timeJump:', {
64+
componentName: targetSnapshot.name,
65+
hasHooksIndex: !!hooksIndex,
66+
hooksState,
67+
reducerStates,
68+
});
6669

67-
// ------------------------STATEFUL CLASS COMPONENT-------------------------
70+
// Handle class components
6871
if (index !== null) {
6972
const classComponent = componentActionsRecord.getComponentByIndex(index);
7073
if (classComponent !== undefined) {
@@ -74,27 +77,55 @@ async function updateReactFiberTree(
7477
return;
7578
}
7679

77-
// ----------------------STATEFUL FUNCTIONAL COMPONENT----------------------
80+
// Handle hooks
7881
if (hooksIndex !== null) {
7982
const functionalComponent = componentActionsRecord.getComponentByIndexHooks(hooksIndex);
8083

81-
// Handle reducer state if present
82-
if (reducerState) {
83-
try {
84-
// For reducer components, update using the first dispatch function
85-
await functionalComponent[0]?.dispatch(reducerState);
86-
} catch (err) {
87-
console.error('Error updating reducer state:', err);
88-
}
89-
} else {
90-
// Handle normal useState components
91-
for (let i in functionalComponent) {
84+
console.log('Retrieved functional component:', {
85+
hasComponent: !!functionalComponent,
86+
hooksIndexLength: hooksIndex.length,
87+
componentLength: functionalComponent?.length,
88+
});
89+
90+
// Handle regular useState hooks
91+
if (hooksState) {
92+
const stateEntries = Object.entries(hooksState);
93+
94+
for (let i = 0; i < stateEntries.length; i++) {
95+
const [key, value] = stateEntries[i];
9296
if (functionalComponent[i]?.dispatch) {
93-
await functionalComponent[i].dispatch(Object.values(hooksState)[i]);
97+
await functionalComponent[i].dispatch(value);
98+
} else {
99+
console.warn(`No dispatch found for hook ${i}:`, {
100+
key,
101+
value,
102+
hasDispatch: !!functionalComponent[i]?.dispatch,
103+
});
94104
}
95105
}
96106
}
97-
targetSnapshot.children.forEach((child) => updateReactFiberTree(child));
107+
108+
// Handle reducer hooks
109+
if (reducerStates && reducerStates.length > 0) {
110+
console.log('Processing reducer states:', reducerStates);
111+
112+
for (const reducerState of reducerStates) {
113+
const { state, reducerIndex } = reducerState;
114+
const reducer = functionalComponent[reducerIndex];
115+
116+
if (reducer?.dispatch) {
117+
console.log('Dispatching reducer update:', {
118+
reducerIndex,
119+
state,
120+
});
121+
await reducer.dispatch(state);
122+
} else {
123+
console.warn('No dispatch found for reducer:', reducerIndex);
124+
}
125+
}
126+
}
127+
128+
targetSnapshot.children.forEach((child) => updateReactFiberTree(child, circularComponentTable));
98129
return;
99130
}
100131
}

src/backend/types/backendTypes.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,12 @@ export interface ComponentData {
6767
index: number | null;
6868
/** {functional component only} - An object contains all states of the current functional component */
6969
hooksState: {} | null;
70-
reducerState?: {} | null;
71-
/** {functional component only} - An array of index of the bound dispatch method stored in `componentActionsRecord` */
70+
reducerStates?: Array<{
71+
state: any;
72+
lastAction: any;
73+
reducerIndex: number;
74+
hookName: string;
75+
}> /** {functional component only} - An array of index of the bound dispatch method stored in `componentActionsRecord` */;
7276
hooksIndex: number[] | null;
7377
/** An object contains all props of the current component */
7478
props: { [key: string]: any };
@@ -85,11 +89,11 @@ export interface ComponentData {
8589
* @member component - contains bound dispatch method to update state of the current functional component
8690
*/
8791
export interface HookStateItem {
88-
/** states within the current functional component */
89-
state: any;
90-
/** an object contains bound dispatch method to update state of the current functional component */
9192
component: any;
92-
isReducer?: boolean;
93+
state: any;
94+
isReducer: boolean;
95+
lastAction?: any;
96+
reducer?: Function;
9397
}
9498

9599
export type WorkTag =

0 commit comments

Comments
 (0)