Skip to content

Bug: Unexpected warning in react-hooks/exhaustive-deps using optional chaining operator #18985

@jcestibariz

Description

@jcestibariz

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;
};

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions