@samitouri / QOS-React-2 / commits / 7992ca10df

eslint-plugin-react-hooks: allow OptionalMemberExpression in deps (#18819) (#18820)

* eslint-plugin-react-hooks: allow OptionalMemberExpression in deps (#18819) * add test case for #18819 * fix test * run prettier

Kevin Lewis committed May 5, 2020 at 05:53 UTC 7992ca10df497002e0e91bb5bfbc9661c9c85b88
2 files changed +39 -1
packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js
+32
@@ -1755,6 +1755,38 @@ const tests = {
1755 },
1756 ],
1757 },
1758 + {
1759 + code: normalizeIndent`
1760 + function MyComponent({ history }) {
1761 + useEffect(() => {
1762 + return [
1763 + history?.foo
1764 + ];
1765 + }, []);
1766 + }
1767 + `,
1768 + errors: [
1769 + {
1770 + message:
1771 + "React Hook useEffect has a missing dependency: 'history?.foo'. " +
1772 + 'Either include it or remove the dependency array.',
1773 + suggestions: [
1774 + {
1775 + desc: 'Update the dependencies array to be: [history?.foo]',
1776 + output: normalizeIndent`
1777 + function MyComponent({ history }) {
1778 + useEffect(() => {
1779 + return [
1780 + history?.foo
1781 + ];
1782 + }, [history?.foo]);
1783 + }
1784 + `,
1785 + },
1786 + ],
1787 + },
1788 + ],
1789 + },
1790 {
1791 code: normalizeIndent`
1792 function MyComponent() {
packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js
+7 -1
@@ -1429,7 +1429,8 @@ function scanForDeclaredBareFunctions({
1429 */
1430 function getDependency(node) {
1431 if (
1432 - node.parent.type === 'MemberExpression' &&
1432 + (node.parent.type === 'MemberExpression' ||
1433 + node.parent.type === 'OptionalMemberExpression') &&
1434 node.parent.object === node &&
1435 node.parent.property.name !== 'current' &&
1436 !node.parent.computed &&
@@ -1456,6 +1457,7 @@ function getDependency(node) {
1457 * (foo) -> 'foo'
1458 * foo.(bar) -> 'foo.bar'
1459 * foo.bar.(baz) -> 'foo.bar.baz'
1460 + * foo?.(bar) -> 'foo?.bar'
1461 * Otherwise throw.
1462 */
1463 function toPropertyAccessString(node) {
@@ -1465,6 +1467,10 @@ function toPropertyAccessString(node) {
1467 const object = toPropertyAccessString(node.object);
1468 const property = toPropertyAccessString(node.property);
1469 return `${object}.${property}`;
1470 + } else if (node.type === 'OptionalMemberExpression' && !node.computed) {
1471 + const object = toPropertyAccessString(node.object);
1472 + const property = toPropertyAccessString(node.property);
1473 + return `${object}?.${property}`;
1474 } else {
1475 throw new Error(`Unsupported node type: ${node.type}`);
1476 }