react: Bug: Unexpected warning in react-hooks/exhaustive-deps using optional chaining operator
When the optional chaining operator (?.) is used inside a hook and the variable is already listed in the dependencies eslint-plugin-react-hooks reports an unexpected “missing dependency” warning. Replacing ?. with . produces the expected behaviour: the warning is no longer reported.
I would expect that the optional chaining operator (?.) be handled as normal property access (.) in the context of this validation.
React version: 16.13.1 eslint-plugin-react-hooks version: 4.0.2
Steps To Reproduce
Notice that foo is both referenced inside the code in useEffect and is listed as a dependency.
import React, {useEffect} from 'react';
const getFoo = () => undefined;
const doSomethingWith = (foo) => {};
export default () => {
  const foo = getFoo();
  useEffect(() => {
    if (foo?.bar) {
      doSomethingWith(foo);
    }
  }, [foo]);
  return null;
};
package.json
{
  "name": "react-hooks-bug",
  "version": "1.0.0",
  "description": "",
  "license": "ISC",
  "scripts": {
    "test": "eslint test.js"
  },
  "dependencies": {
    "babel-eslint": "^10.1.0",
    "eslint": "^7.1.0",
    "eslint-plugin-react-hooks": "^4.0.2"
  },
  "eslintConfig": {
    "parser": "babel-eslint",
    "parserOptions": {
      "sourceType": "module"
    },
    "plugins": [
      "react-hooks"
    ],
    "rules": {
      "react-hooks/exhaustive-deps": "warn"
    }
  }
}
The current behavior
The following warning is reported:
warning React Hook useEffect has a missing dependency: 'foo?.bar'. Either include it or remove the dependency array  react-hooks/exhaustive-deps
The expected behavior
No warning should be reported.
Additional notes
With the following code, which only replaces ?. with ., eslint-plugin-react-hooks behaves as expected, that is no warning is reported. (Of course this fails at runtime when foo is undefined).
import React, {useEffect} from 'react';
const getFoo = () => undefined;
const doSomethingWith = (foo) => {};
export default () => {
  const foo = getFoo();
  useEffect(() => {
    if (foo.bar) {
      doSomethingWith(foo);
    }
  }, [foo]);
  return null;
};
About this issue
- Original URL
 - State: closed
 - Created 4 years ago
 - Reactions: 9
 - Comments: 19 (3 by maintainers)
 
Commits related to this issue
- fix(eslint-plugin-react-hooks): Added test cases for nullish coalescing and optional chaining of dependencies, relates to #18985 — committed to yanneves/react by yanneves 4 years ago
 - fix(eslint-plugin-react-hooks): Added matching for nullish coalescing and optional chaining of dependencies, relates to #18985 — committed to yanneves/react by yanneves 4 years ago
 - fix(eslint-plugin-react-hooks): Added matching for nullish coalescing and optional chaining of dependencies, relates to #18985 (#19008) — committed to facebook/react by yanneves 4 years ago
 
eslint-plugin-react-hooks@4.0.4Sorry, yes, you are right, I missed the
doSomethingWith(foo);Yeah, that is probably right, I see if you write this without optional chaining it would look like
and that does not produce an eslint error.
I’m hitting this too with latest exhaustive-deps
Yeah, we are getting the same bug as well. Any hints on how to solve the problem? : ) Thank you!
Update:
This was just fixed in https://github.com/facebook/react/pull/19062 😹 Thank you so much!
@yanneves You’re right it’s basically the same check. Thank you for checking.
If it ever happens again I’ll know pretty soon after 😃
Happy to take a fix!