Skip to content

Bug: [eslint-plugin-react-hooks] exhaustive-deps false positive on "unnecessary" dependency if its a React component #18051

@zeorin

Description

@zeorin

Steps to reproduce

  1. create a memoized value using useMemo
  2. a React component is used in the creation of this value, in a JSX expression
  3. specify the React component in the dependency array

Link to code example: https://github.com/zeorin/eslint-plugin-react-hooks-repro

The current behavior

React Hook useMemo has an unnecessary dependency: 'Component'. Either exclude it or remove the dependency array react-hooks/exhaustive-deps

The expected behavior

No lint errors.

More details

A simple repro (taken from the link above) is:

function Foo({ component: Component }) {
	const memoized = useMemo(() => ({
		render: () => <Component />
	}), [Component]);

	return memoized.render();
}

Workarounds

If one changes the component to lowercase, the lint error goes away. It does also mean that we need to change the way we render the component:

function Foo({ component }) {
	const memoized = useMemo(() => ({
		render: component
	}), [component]);

	return memoized.render();
}

Alternatively we can decide not to use JSX, in which case the lint rule functions correctly, too:

function Foo({ component: Component }) {
	const memoized = useMemo(() => ({
		render: () => React.createElement(Component)
	}), [Component]);

	return memoized.render();
}

Impact

Currently it is hard to use props that are components in a JSX expression if one is using the exhaustive-deps rule.

This is also compounded by the fact that this rule has a ESLint fix that removes the dependency, thus changing the behaviour of the code and leading to bugs. See #16313 for that bug report.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions