Skip to content

Commit f85e789

Browse files
committed
change state using arrow functions instead
1 parent 795c899 commit f85e789

File tree

4 files changed

+190
-34
lines changed

4 files changed

+190
-34
lines changed

source/index.ts

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ interface ToModifyVariableI {
55
simplified: string
66
}
77

8-
export default function () {
8+
export default function toMutableTransformer() {
99
const toMod: ToModifyVariableI[] = []
1010
return {
1111
visitor: {
@@ -46,9 +46,21 @@ function transformToStateByScope(path: any, toMod: ToModifyVariableI[]) {
4646
VariableDeclaration({node}: {node: t.VariableDeclaration}) {
4747
transformReactiveDeclarations(node, toMod, path)
4848
},
49-
ExpressionStatement({node}: {node: t.ExpressionStatement}) {
50-
transformAssignmentExpression(node, toMod)
49+
ExpressionStatement(expressionPath: any) {
50+
const node: t.ExpressionStatement = expressionPath.node
51+
const replacedStateExpression = transformAssignmentExpression(
52+
node,
53+
toMod,
54+
expressionPath
55+
)
5156
transformUpdateExpression(node, toMod)
57+
58+
// HACK: any identifier inside the replace expression that is reactive to change itself to
59+
// the substate name so $a => a => _prevState
60+
if (replacedStateExpression) {
61+
const {subStateIdentifier, normName} = replacedStateExpression
62+
replaceIdentifiers(expressionPath, normName, subStateIdentifier.name)
63+
}
5264
},
5365
})
5466
}
@@ -92,7 +104,8 @@ function transformReactiveDeclarations(
92104

93105
function transformAssignmentExpression(
94106
node: t.ExpressionStatement,
95-
toMod: ToModifyVariableI[]
107+
toMod: ToModifyVariableI[],
108+
path: any
96109
) {
97110
if (!t.isAssignmentExpression(node.expression)) {
98111
return
@@ -112,47 +125,52 @@ function transformAssignmentExpression(
112125
const normName = normalizeName(expression.left.name)
113126
const setterName = getSetterName(normName)
114127

115-
let callArgs: t.Expression[]
128+
const subStateIdentifier: t.Identifier =
129+
path.scope.generateUidIdentifier('prevState')
130+
131+
let params: any = {}
116132

117133
switch (expression.operator) {
118134
case '=': {
119-
callArgs = [{...expression.right}]
135+
params = expression.right
120136
break
121137
}
122138

123139
case '+=': {
124-
callArgs = [
125-
t.binaryExpression('+', t.identifier(normName), expression.right),
126-
]
140+
params = t.binaryExpression('+', subStateIdentifier, expression.right)
127141
break
128142
}
129143

130144
case '-=': {
131-
callArgs = [
132-
t.binaryExpression('-', t.identifier(normName), expression.right),
133-
]
145+
params = t.binaryExpression('-', subStateIdentifier, expression.right)
134146
break
135147
}
136148

137149
case '/=': {
138-
callArgs = [
139-
t.binaryExpression('/', t.identifier(normName), expression.right),
140-
]
150+
params = t.binaryExpression('/', subStateIdentifier, expression.right)
151+
141152
break
142153
}
143154

144155
case '*=': {
145-
callArgs = [
146-
t.binaryExpression('*', t.identifier(normName), expression.right),
147-
]
156+
params = t.binaryExpression('*', subStateIdentifier, expression.right)
148157
break
149158
}
150159
default: {
151-
callArgs = []
160+
params = []
152161
}
153162
}
154163

155-
node.expression = t.callExpression(t.identifier(setterName), callArgs)
164+
let arrowExpression = params
165+
if (!t.isArrowFunctionExpression(params)) {
166+
arrowExpression = t.arrowFunctionExpression([subStateIdentifier], params)
167+
}
168+
169+
node.expression = t.callExpression(t.identifier(setterName), [
170+
arrowExpression,
171+
])
172+
173+
return {subStateIdentifier, normName, setterName}
156174
}
157175

158176
function transformUpdateExpression(
@@ -211,3 +229,13 @@ function getSetterName(normalizedName: string) {
211229
function normalizeName(n: string) {
212230
return n.replace(/\$/, '')
213231
}
232+
233+
function replaceIdentifiers(path: any, toCompare: string, replaceWith: string) {
234+
return path.traverse({
235+
Identifier({node}: {node: t.Identifier}) {
236+
if (node.name === toCompare) {
237+
node.name = replaceWith
238+
}
239+
},
240+
})
241+
}

test/snapshots/test.ts.md

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ The actual snapshot is saved in `test.ts.snap`.
44

55
Generated by [AVA](https://avajs.dev).
66

7-
## works
7+
## Simple Transform
88

99
> Snapshot 1
1010
@@ -14,15 +14,15 @@ Generated by [AVA](https://avajs.dev).
1414
const [a, setA] = React.useState(1);␊
1515
1616
const onPress = () => {␊
17-
setA(a + 1);␊
17+
setA(_prevState => _prevState + 1);␊
1818
};␊
1919
2020
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("p", null, a), /*#__PURE__*/React.createElement("button", {␊
2121
onClick: onPress␊
2222
}, "Press"));␊
2323
}`
2424

25-
## Simple Transform
25+
## Simple Transform 2
2626

2727
> Snapshot 1
2828
@@ -32,14 +32,37 @@ Generated by [AVA](https://avajs.dev).
3232
const [a, setA] = React.useState(1);␊
3333
3434
const onPress = () => {␊
35-
setA(a + 1);␊
35+
setA(x => {␊
36+
console.log(x);␊
37+
return x + 1;␊
38+
});␊
3639
};␊
3740
3841
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("p", null, a), /*#__PURE__*/React.createElement("button", {␊
3942
onClick: onPress␊
4043
}, "Press"));␊
4144
}`
4245

46+
## Simple Transform 3
47+
48+
> Snapshot 1
49+
50+
`import * as React from "react";␊
51+
52+
function Component() {␊
53+
const [a, setA] = React.useState("");␊
54+
55+
const onChange = e => {␊
56+
setA(_prevState => e.target.value);␊
57+
setA(_prevState2 => _prevState2.toUpperCase());␊
58+
};␊
59+
60+
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("input", {␊
61+
value: a,␊
62+
onChange: onChange␊
63+
}));␊
64+
}`
65+
4366
## Check Functional Scope
4467

4568
> Snapshot 1
@@ -51,7 +74,7 @@ Generated by [AVA](https://avajs.dev).
5174
const [a, setA] = React.useState(1);␊
5275
5376
const onPress = () => {␊
54-
setA(a + 1);␊
77+
setA(_prevState => _prevState + 1);␊
5578
$b = 3;␊
5679
};␊
5780
@@ -71,7 +94,7 @@ Generated by [AVA](https://avajs.dev).
7194
const [a, setA] = React.useState(1);␊
7295
7396
const onPress = () => {␊
74-
setA(a + 1);␊
97+
setA(_prevState => _prevState + 1);␊
7598
$b = 3;␊
7699
};␊
77100
@@ -91,7 +114,7 @@ Generated by [AVA](https://avajs.dev).
91114
const [a, setA] = React.useState(1);␊
92115
93116
const onPress = () => {␊
94-
setA(a + 1);␊
117+
setA(_prevState => _prevState + 1);␊
95118
$b = 3;␊
96119
};␊
97120
@@ -104,7 +127,7 @@ Generated by [AVA](https://avajs.dev).
104127
const [a, setA] = React.useState(3);␊
105128
106129
const onPress = () => {␊
107-
setA(5);␊
130+
setA(_prevState2 => 5);␊
108131
$b = 3;␊
109132
};␊
110133
@@ -126,7 +149,7 @@ Generated by [AVA](https://avajs.dev).
126149
}, [a]);␊
127150
128151
const onPress = () => {␊
129-
setA(a + 1);␊
152+
setA(_prevState => _prevState + 1);␊
130153
};␊
131154
132155
return {␊
@@ -144,8 +167,8 @@ Generated by [AVA](https://avajs.dev).
144167
const [count, setCount] = React.useState(1);␊
145168
146169
const handleClick = () => {␊
147-
setCount(count + 1);␊
148-
setCount(count * 2);␊
170+
setCount(_prevState => _prevState + 1);␊
171+
setCount(_prevState2 => _prevState2 * 2);␊
149172
};␊
150173
151174
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", null, count), /*#__PURE__*/React.createElement("button", {␊
@@ -168,7 +191,31 @@ Generated by [AVA](https://avajs.dev).
168191
const x = { ...user␊
169192
};␊
170193
x.name = "barelyhuman";␊
171-
setUser(x);␊
194+
setUser(_prevState => x);␊
195+
};␊
196+
197+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", null, user.name), /*#__PURE__*/React.createElement("button", {␊
198+
onClick: updateUser␊
199+
}, "Click Me"));␊
200+
}`
201+
202+
## Object Update Arrow Func
203+
204+
> Snapshot 1
205+
206+
`import * as React from "react";␊
207+
208+
function App() {␊
209+
const [user, setUser] = React.useState({␊
210+
name: "reaper"␊
211+
});␊
212+
213+
const updateUser = () => {␊
214+
setUser(x => Object.assign({}, {␊
215+
x␊
216+
}, {␊
217+
name: "barelyhuman"␊
218+
}));␊
172219
};␊
173220
174221
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", null, user.name), /*#__PURE__*/React.createElement("button", {␊
@@ -191,7 +238,7 @@ Generated by [AVA](https://avajs.dev).
191238
const _nextUsers = users.slice();␊
192239
193240
_nextUsers[0].name = "barelyhuman";␊
194-
setUser(_nextUsers);␊
241+
setUsers(_prevState => _nextUsers);␊
195242
};␊
196243
197244
return /*#__PURE__*/React.createElement(React.Fragment, null, users.map(user => {␊

test/snapshots/test.ts.snap

-1.01 KB
Binary file not shown.

0 commit comments

Comments
 (0)