fix(eslint-plugin-react-hooks): Support optional chaining when accessing prototype method inside useCallback and useMemo #19061 (#19062)

* fix(eslint-plugin-react-hooks): Support optional chaining when accessing prototype method #19061

* run prettier

* Add fix for #19043
This commit is contained in:
Fred Vollmer 2020-06-30 07:14:00 -04:00 committed by GitHub
parent e9c1445ba0
commit b0533fe33c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 2 deletions

View File

@ -289,6 +289,24 @@ const tests = {
}
`,
},
{
code: normalizeIndent`
function MyComponent(props) {
useMemo(() => {
console.log(props.foo?.toString());
}, [props.foo]);
}
`,
},
{
code: normalizeIndent`
function MyComponent(props) {
useCallback(() => {
console.log(props.foo?.toString());
}, [props.foo]);
}
`,
},
{
code: normalizeIndent`
function MyComponent() {
@ -1235,6 +1253,35 @@ const tests = {
},
],
invalid: [
{
code: normalizeIndent`
function MyComponent(props) {
useCallback(() => {
console.log(props.foo?.toString());
}, []);
}
`,
errors: [
{
message:
"React Hook useCallback has a missing dependency: 'props.foo?.toString'. " +
'Either include it or remove the dependency array.',
suggestions: [
{
desc:
'Update the dependencies array to be: [props.foo?.toString]',
output: normalizeIndent`
function MyComponent(props) {
useCallback(() => {
console.log(props.foo?.toString());
}, [props.foo?.toString]);
}
`,
},
],
},
],
},
{
code: normalizeIndent`
function MyComponent() {

View File

@ -1287,10 +1287,13 @@ function collectRecommendations({
function scanTreeRecursively(node, missingPaths, satisfyingPaths, keyToPath) {
node.children.forEach((child, key) => {
const path = keyToPath(key);
// For analyzing dependencies, we want the "normalized" path, without any optional chaining ("?.") operator
// foo?.bar -> foo.bar
const normalizedPath = path.replace(/\?$/, '');
if (child.isSatisfiedRecursively) {
if (child.hasRequiredNodesBelow) {
// Remember this dep actually satisfied something.
satisfyingPaths.add(path);
satisfyingPaths.add(normalizedPath);
}
// It doesn't matter if there's something deeper.
// It would be transitively satisfied since we assume immutability.
@ -1299,7 +1302,7 @@ function collectRecommendations({
}
if (child.isRequired) {
// Remember that no declared deps satisfied this node.
missingPaths.add(path);
missingPaths.add(normalizedPath);
// If we got here, nothing in its subtree was satisfied.
// No need to search further.
return;