Skip to content

Commit 635c617

Browse files
[Fix] destructuring-assignment: Handle destructuring of useContext in
SFC
1 parent 153eac8 commit 635c617

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

lib/rules/destructuring-assignment.js

+31-4
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ module.exports = {
3838
create: Components.detect((context, components, utils) => {
3939
const configuration = context.options[0] || DEFAULT_OPTION;
4040
const ignoreClassFields = context.options[1] && context.options[1].ignoreClassFields === true || false;
41-
41+
// set to save renamed var of useContext
42+
const contextSet = new Set();
4243
/**
4344
* @param {ASTNode} node We expect either an ArrowFunctionExpression,
4445
* FunctionDeclaration, or FunctionExpression
@@ -61,14 +62,24 @@ module.exports = {
6162
}
6263

6364
function handleSFCUsage(node) {
64-
// props.aProp || context.aProp
65-
const isPropUsed = (node.object.name === 'props' || node.object.name === 'context') && !isAssignmentLHS(node);
65+
// props.aProp
66+
const isPropUsed = (node.object.name === 'props') && !isAssignmentLHS(node);
6667
if (isPropUsed && configuration === 'always') {
6768
context.report({
6869
node,
6970
message: `Must use destructuring ${node.object.name} assignment`
7071
});
7172
}
73+
74+
// const foo = useContext(aContext);
75+
// foo.aProp
76+
const isContextUsed = contextSet.has(node.object.name) && !isAssignmentLHS(node);
77+
if (isContextUsed && configuration === 'always') {
78+
context.report({
79+
node,
80+
message: `Must use destructuring ${node.object.name} assignment`
81+
});
82+
}
7283
}
7384

7485
function isInClassProperty(node) {
@@ -125,13 +136,29 @@ module.exports = {
125136
const SFCComponent = components.get(context.getScope(node).block);
126137

127138
const destructuring = (node.init && node.id && node.id.type === 'ObjectPattern');
139+
const identifier = (node.init && node.id && node.id.type === 'Identifier');
128140
// let {foo} = props;
129-
const destructuringSFC = destructuring && (node.init.name === 'props' || node.init.name === 'context');
141+
const destructuringSFC = destructuring && node.init.name === 'props';
142+
// let {foo} = useContext(aContext);
143+
const destructuringUseContext = destructuring && node.init.callee && node.init.callee.name === 'useContext';
144+
// let foo = useContext(aContext);
145+
const assignUseContext = identifier && node.init.callee && node.init.callee.name === 'useContext';
130146
// let {foo} = this.props;
131147
const destructuringClass = destructuring && node.init.object && node.init.object.type === 'ThisExpression' && (
132148
node.init.property.name === 'props' || node.init.property.name === 'context' || node.init.property.name === 'state'
133149
);
134150

151+
if (SFCComponent && assignUseContext) {
152+
contextSet.add(node.id.name);
153+
}
154+
155+
if (SFCComponent && destructuringUseContext && configuration === 'never') {
156+
context.report({
157+
node,
158+
message: `Must never use destructuring ${node.init.callee.name} assignment`
159+
});
160+
}
161+
135162
if (SFCComponent && destructuringSFC && configuration === 'never') {
136163
context.report({
137164
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)