Skip to content

Commit d032842

Browse files
committed
fixup! [New] Symmetric useState hook variable names
1 parent f66510b commit d032842

File tree

2 files changed

+86
-77
lines changed

2 files changed

+86
-77
lines changed

lib/rules/hook-use-state.js

Lines changed: 52 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const report = require('../util/report');
1515

1616
const messages = {
1717
useStateErrorMessage: 'useState call is not destructured into value + setter pair',
18+
1819
};
1920

2021
module.exports = {
@@ -136,75 +137,65 @@ module.exports = {
136137
&& variableNodes.length === 2;
137138

138139
if (!isSymmetricGetterSetterPair) {
140+
const suggestions = [
141+
{
142+
desc: 'Destructure useState call into value + setter pair',
143+
fix: (fixer) => {
144+
const fix = fixer.replaceTextRange(
145+
node.parent.id.range,
146+
`[${valueVariableName}, ${expectedSetterVariableName}]`
147+
);
148+
149+
return fix;
150+
},
151+
},
152+
];
153+
139154
const isSingleGetter = valueVariable && variableNodes.length === 1;
140155
const isUseStateCalledWithSingleArgument = node.arguments.length === 1;
141156
if (isSingleGetter && isUseStateCalledWithSingleArgument) {
142157
const useMemoReactImportSpecifier = namedReactImports ? namedReactImports.find((specifier) => specifier.imported.name === 'useMemo') : undefined;
143158
const sourceCode = context.getSourceCode();
144159
const useStateArgumentSourceCode = sourceCode.getText(node.arguments[0]);
145160

146-
report(
147-
context,
148-
messages.useStateErrorMessage,
149-
'useStateErrorMessage',
150-
{
151-
node: node.parent.id,
152-
suggest: [
153-
{
154-
desc: 'Replace useState call with useMemo',
155-
fix: (fixer) => {
156-
const useMemoImportName = useMemoReactImportSpecifier && useMemoReactImportSpecifier.local.name;
157-
158-
const useMemoReference = useMemoImportName
159-
|| (defaultReactImportName
160-
&& `${defaultReactImportName}.useMemo`)
161-
|| 'useMemo';
162-
163-
const fixes = [
164-
// Add useMemo import, if necessary
165-
useStateReactImportSpecifier
166-
&& (!useMemoReactImportSpecifier || defaultReactImportName)
167-
&& fixer.insertTextAfter(useStateReactImportSpecifier, ', useMemo'),
168-
// Convert single-value destructure to simple assignment
169-
fixer.replaceTextRange(node.parent.id.range, valueVariableName),
170-
// Convert useState call to useMemo + arrow function + dependency array
171-
fixer.replaceTextRange(
172-
node.range,
173-
`${useMemoReference}(() => ${useStateArgumentSourceCode}, [])`
174-
),
175-
].filter(Boolean);
176-
177-
return fixes;
178-
},
179-
},
180-
{
181-
desc: 'Destructure useState call into value + setter pair',
182-
fix: (fixer) => {
183-
const fix = fixer.replaceTextRange(
184-
node.parent.id.range,
185-
`[${valueVariableName}, ${expectedSetterVariableName}]`
186-
);
187-
188-
return fix;
189-
},
190-
},
191-
].filter(Boolean),
192-
}
193-
);
194-
} else {
195-
report(
196-
context,
197-
messages.useStateErrorMessage,
198-
'useStateErrorMessage',
199-
{
200-
node: node.parent.id,
201-
fix: valueVariableName ? (fixer) => fixer.replaceTextRange(
202-
[node.parent.id.range[0], node.parent.id.range[1]],
203-
`[${valueVariableName}, ${expectedSetterVariableName}]`
204-
) : undefined,
205-
}
206-
);
161+
suggestions.unshift({
162+
desc: 'Replace useState call with useMemo',
163+
fix: (fixer) => {
164+
const useMemoImportName = useMemoReactImportSpecifier && useMemoReactImportSpecifier.local.name;
165+
166+
const useMemoReference = useMemoImportName
167+
|| (defaultReactImportName
168+
&& `${defaultReactImportName}.useMemo`)
169+
|| 'useMemo';
170+
171+
const fixes = [
172+
// Add useMemo import, if necessary
173+
useStateReactImportSpecifier
174+
&& (!useMemoReactImportSpecifier || defaultReactImportName)
175+
&& fixer.insertTextAfter(useStateReactImportSpecifier, ', useMemo'),
176+
// Convert single-value destructure to simple assignment
177+
fixer.replaceTextRange(node.parent.id.range, valueVariableName),
178+
// Convert useState call to useMemo + arrow function + dependency array
179+
fixer.replaceTextRange(
180+
node.range,
181+
`${useMemoReference}(() => ${useStateArgumentSourceCode}, [])`
182+
),
183+
].filter(Boolean);
184+
185+
return fixes;
186+
},
187+
});
207188
}
189+
190+
report(
191+
context,
192+
messages.useStateErrorMessage,
193+
'useStateErrorMessage',
194+
{
195+
node: node.parent.id,
196+
suggest: suggestions,
197+
}
198+
);
208199
}
209200
},
210201
})),

tests/lib/rules/hook-use-state.js

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,15 @@ const tests = {
230230
}`,
231231
errors: [{
232232
message: 'useState call is not destructured into value + setter pair',
233-
}],
234-
output: `import { useState } from 'react'
233+
suggestions: [
234+
{
235+
output: `import { useState } from 'react'
235236
export default function useColor() {
236237
const [color, setColor] = useState()
237238
}`,
239+
},
240+
],
241+
}],
238242
},
239243
{
240244
code: `import { useState } from 'react'
@@ -319,12 +323,14 @@ const tests = {
319323
}`,
320324
errors: [{
321325
message: 'useState call is not destructured into value + setter pair',
322-
}],
323-
output: `import { useState } from 'react'
326+
suggestions: [{
327+
output: `import { useState } from 'react'
324328
export default function useColor() {
325329
const [color, setColor] = useState()
326330
return [color]
327331
}`,
332+
}],
333+
}],
328334
},
329335
{
330336
code: `import { useState } from 'react'
@@ -334,12 +340,14 @@ const tests = {
334340
}`,
335341
errors: [{
336342
message: 'useState call is not destructured into value + setter pair',
337-
}],
338-
output: `import { useState } from 'react'
343+
suggestions: [{
344+
output: `import { useState } from 'react'
339345
export default function useColor() {
340346
const [color, setColor] = useState()
341347
return [color, setColor]
342348
}`,
349+
}],
350+
}],
343351
},
344352
{
345353
code: `import { useState } from 'react'
@@ -353,27 +361,33 @@ const tests = {
353361
const [color, setFlavor, extraneous] = useState()`,
354362
errors: [{
355363
message: 'useState call is not destructured into value + setter pair',
356-
}],
357-
output: `import { useState } from 'react'
364+
suggestions: [{
365+
output: `import { useState } from 'react'
358366
const [color, setColor] = useState()`,
367+
}],
368+
}],
359369
},
360370
{
361371
code: `import { useState } from 'react'
362372
const [color, setFlavor] = useState()`,
363373
errors: [{
364374
message: 'useState call is not destructured into value + setter pair',
365-
}],
366-
output: `import { useState } from 'react'
375+
suggestions: [{
376+
output: `import { useState } from 'react'
367377
const [color, setColor] = useState()`,
378+
}],
379+
}],
368380
},
369381
{
370382
code: `import { useState } from 'react'
371383
const [color, setFlavor] = useState<string>()`,
372384
errors: [{
373385
message: 'useState call is not destructured into value + setter pair',
374-
}],
375-
output: `import { useState } from 'react'
386+
suggestions: [{
387+
output: `import { useState } from 'react'
376388
const [color, setColor] = useState<string>()`,
389+
}],
390+
}],
377391
features: ['ts', 'no-babel-old'],
378392
},
379393
{
@@ -384,12 +398,14 @@ const tests = {
384398
}`,
385399
errors: [{
386400
message: 'useState call is not destructured into value + setter pair',
387-
}],
388-
output: `import { useState } from 'react'
401+
suggestions: [{
402+
output: `import { useState } from 'react'
389403
export default function useColor() {
390404
const [color, setColor] = useState<string>('#ffffff')
391405
return [color, setFlavor]
392406
}`,
407+
}],
408+
}],
393409
features: ['ts', 'no-babel-old'],
394410
},
395411
{
@@ -400,12 +416,14 @@ const tests = {
400416
}`,
401417
errors: [{
402418
message: 'useState call is not destructured into value + setter pair',
403-
}],
404-
output: `import React from 'react'
419+
suggestions: [{
420+
output: `import React from 'react'
405421
export default function useColor() {
406422
const [color, setColor] = React.useState<string>('#ffffff')
407423
return [color, setFlavor]
408424
}`,
425+
}],
426+
}],
409427
features: ['ts', 'no-babel-old'],
410428
},
411429
]),

0 commit comments

Comments
 (0)