Skip to content

Commit 690ad51

Browse files
MarkTeetsminzo-kim
andcommitted
Fixed useState ES6 related bugs
Co-authored-by: minzo-kim <[email protected]>
1 parent 7803dc2 commit 690ad51

File tree

1 file changed

+41
-6
lines changed

1 file changed

+41
-6
lines changed

src/backend/controllers/statePropExtractors.ts

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ export function getHooksStateAndUpdateMethod(
8383

8484
// ---------------------GET STATE VAR NAME & HOOK NAME--------------------------
8585
/**
86-
* This function receive a string representation of a functional component. This function then use JSX parser to traverse through the function string, and extract the state variable name and its corresponding setState method.
86+
* This function receive a string representation of a functional component.
87+
* This function then uses JSX parser to traverse through the function string,
88+
* and extract the state variable name and its corresponding setState method.
8789
* @param elementType - The string representation of a functional component
8890
* @returns - An array of objects with key: hookName (the name of setState method) | value: varName (the state variable name)
8991
*/
@@ -93,45 +95,78 @@ export function getHooksNames(elementType: string): { hookName: string; varName:
9395
let AST: any;
9496
try {
9597
AST = JSXParser.parse(elementType).body;
98+
console.log('AST');
99+
console.log(AST);
100+
let count = 0;
96101
// Begin search for hook names, only if ast has a body property.
97102
// Statements get all the names of the hooks. For example: useCount, useWildcard, ...
98103
const statements: { hookName: string; varName: string }[] = [];
99104
/** All module exports always start off as a single 'FunctionDeclaration' type
100105
* Other types: "BlockStatement" / "ExpressionStatement" / "ReturnStatement"
101-
* Iterate through AST of every function declaration
102-
* Check within each function declaration if there are hook declarations & variable name declaration */
106+
* Iterate through AST of every function(al component) declaration
107+
* Check within each function(al component) declaration if there are hook declarations & variable name declaration */
103108
AST.forEach((functionDec: any) => {
109+
// console.log('functionDec');
110+
// console.log(functionDec);
104111
let declarationBody: any;
105112
if (functionDec.expression?.body) declarationBody = functionDec.expression.body.body;
106113
// check if functionDec.expression.body exists, then set declarationBody to functionDec's body
107114
else declarationBody = functionDec.body?.body ?? [];
108115
// Traverse through the function's funcDecs and Expression Statements
116+
console.log('declarationBody');
117+
console.log( declarationBody);
109118
declarationBody.forEach((elem: any) => {
110119
// Hooks will always be contained in a variable declaration
120+
console.log('elem type:', count++, elem.type);
121+
console.log(elem);
122+
111123
if (elem.type === 'VariableDeclaration') {
112124
// Obtain the declarations array from elem.
113125
const { declarations } = elem;
114126
// Obtain the reactHook:
115127
// Due to difference in babel transpilation in browser vs for jest test, expression is stored in differen location
128+
console.log('Found variable declaration, elem declarations:', declarations)
129+
// console.log('dec[0]', declarations[0]);
130+
// console.log('init',declarations[0]?.init);
131+
// console.log('callee',declarations[0]?.init?.callee);
132+
// console.log('expressions', declarations[0]?.init?.callee?.expressions);
133+
// console.log('Line 2!');
134+
// console.log('args', declarations[0]?.init?.arguments);
135+
// console.log('args[0]', declarations[0]?.init?.arguments?.arguments[0]);
136+
// console.log('callee', declarations[0]?.init?.arguments?.arguments[0]?.callee);
137+
// console.log('expression', declarations[0]?.init?.arguments?.arguments[0]?.callee?.expressions);
116138
const expression =
117139
declarations[0]?.init?.callee?.expressions || //work for browser
118-
declarations[0]?.init?.arguments[0]?.callee?.expressions; //work for jest test
140+
//Mark's notes: so this was where the app was breaking. ES6 functions (e.g. const handleClick = () => {}) inside functional components were hitting this line and crashing when it tried to access arguments[0] and arguments didn't exist.
141+
declarations[0]?.init?.arguments?.[0]?.callee?.expressions; //work for jest test;
142+
143+
console.log('looked for expression, found:', expression);
144+
//Mark's Note: for a functional definition that isn't a hook, it won't have the callee being searched for above. This line will cause this forEach execution to stop here in this case.
145+
if (expression === undefined) return;
119146
let reactHook: string;
120147
reactHook = expression[1].property?.name;
121148
if (reactHook === 'useState') {
122149
// Obtain the variable being set:
150+
//Mark's note: changed to point to second to last element of declarations because webpack adds an extra variable when converting files that use ES6, so the previous pointer wasn't working for this case
123151
let varName: string =
124-
declarations[1]?.id?.name || // work react application
152+
declarations[declarations.length - 2]?.id?.name || // work react application;
125153
(Array.isArray(declarations[0]?.id?.elements)
126154
? declarations[0]?.id?.elements[0]?.name
127155
: undefined); //work for nextJS application
128156
// Obtain the setState method:
157+
//Mark's note: changed to point to last element of declarations because webpack adds an extra variable when converting files that use ES6, so the previous pointer wasn't working for this case
129158
let hookName: string =
130-
declarations[2]?.id?.name || // work react application
159+
declarations[declarations.length - 1]?.id?.name || // work react application;
131160
(Array.isArray(declarations[0]?.id?.elements)
132161
? declarations[0]?.id?.elements[0]?.name
133162
: undefined); //work for nextJS & Remix
134163
// Push reactHook & varName to statements array
164+
/**
165+
* Mark's notes, I'd like to alter the structure of the data
166+
* to pass on the reactHook 'useState'. That way the user will
167+
* eventually be able to view the difference between variables
168+
* stored via useState and useContext
169+
*/
135170
statements.push({ hookName, varName });
136171
}
137172
}

0 commit comments

Comments
 (0)