Skip to content

Commit a5294d6

Browse files
ed-jinyoung-parkljharb
authored andcommitted
[Fix] destructuring-assignment: Handle destructuring of useContext in SFC
1 parent 896fe4b commit a5294d6

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

lib/rules/destructuring-assignment.js

+31-3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ module.exports = {
3939
const configuration = context.options[0] || DEFAULT_OPTION;
4040
const ignoreClassFields = (context.options[1] && (context.options[1].ignoreClassFields === true)) || false;
4141

42+
// set to save renamed var of useContext
43+
const contextSet = new Set();
4244
/**
4345
* @param {ASTNode} node We expect either an ArrowFunctionExpression,
4446
* FunctionDeclaration, or FunctionExpression
@@ -61,14 +63,24 @@ module.exports = {
6163
}
6264

6365
function handleSFCUsage(node) {
64-
// props.aProp || context.aProp
65-
const isPropUsed = (node.object.name === 'props' || node.object.name === 'context') && !isAssignmentLHS(node);
66+
// props.aProp
67+
const isPropUsed = node.object.name === 'props' && !isAssignmentLHS(node);
6668
if (isPropUsed && configuration === 'always') {
6769
context.report({
6870
node,
6971
message: `Must use destructuring ${node.object.name} assignment`
7072
});
7173
}
74+
75+
// const foo = useContext(aContext);
76+
// foo.aProp
77+
const isContextUsed = contextSet.has(node.object.name) && !isAssignmentLHS(node);
78+
if (isContextUsed && configuration === 'always') {
79+
context.report({
80+
node,
81+
message: `Must use destructuring ${node.object.name} assignment`
82+
});
83+
}
7284
}
7385

7486
function isInClassProperty(node) {
@@ -125,13 +137,29 @@ module.exports = {
125137
const SFCComponent = components.get(context.getScope(node).block);
126138

127139
const destructuring = (node.init && node.id && node.id.type === 'ObjectPattern');
140+
const identifier = (node.init && node.id && node.id.type === 'Identifier');
128141
// let {foo} = props;
129-
const destructuringSFC = destructuring && (node.init.name === 'props' || node.init.name === 'context');
142+
const destructuringSFC = destructuring && node.init.name === 'props';
143+
// let {foo} = useContext(aContext);
144+
const destructuringUseContext = destructuring && node.init.callee && node.init.callee.name === 'useContext';
145+
// let foo = useContext(aContext);
146+
const assignUseContext = identifier && node.init.callee && node.init.callee.name === 'useContext';
130147
// let {foo} = this.props;
131148
const destructuringClass = destructuring && node.init.object && node.init.object.type === 'ThisExpression' && (
132149
node.init.property.name === 'props' || node.init.property.name === 'context' || node.init.property.name === 'state'
133150
);
134151

152+
if (SFCComponent && assignUseContext) {
153+
contextSet.add(node.id.name);
154+
}
155+
156+
if (SFCComponent && destructuringUseContext && configuration === 'never') {
157+
context.report({
158+
node,
159+
message: `Must never use destructuring ${node.init.callee.name} assignment`
160+
});
161+
}
162+
135163
if (SFCComponent && destructuringSFC && configuration === 'never') {
136164
context.report({
137165
node,

tests/lib/rules/destructuring-assignment.js

+30
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,18 @@ ruleTester.run('destructuring-assignment', rule, {
176176
].join('\n'),
177177
options: ['always', {ignoreClassFields: true}],
178178
parser: parsers.BABEL_ESLINT
179+
}, {
180+
code: `const MyComponent = (props) => {
181+
const {foo} = useContext(aContext);
182+
return <div>{foo}</div>
183+
};`,
184+
options: ['always']
185+
}, {
186+
code: `const MyComponent = (props) => {
187+
const foo = useContext(aContext);
188+
return <div>{foo.test}</div>
189+
};`,
190+
options: ['never']
179191
}],
180192

181193
invalid: [{
@@ -314,5 +326,23 @@ ruleTester.run('destructuring-assignment', rule, {
314326
errors: [
315327
{message: 'Must never use destructuring state assignment'}
316328
]
329+
}, {
330+
code: `const MyComponent = (props) => {
331+
const foo = useContext(aContext);
332+
return <div>{foo.test}</div>
333+
};`,
334+
options: ['always'],
335+
errors: [
336+
{message: 'Must use destructuring foo assignment'}
337+
]
338+
}, {
339+
code: `const MyComponent = (props) => {
340+
const {foo} = useContext(aContext);
341+
return <div>{foo}</div>
342+
};`,
343+
options: ['never'],
344+
errors: [
345+
{message: 'Must never use destructuring useContext assignment'}
346+
]
317347
}]
318348
});

0 commit comments

Comments
 (0)