Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: ESLint rule doesn't catch mistake with non-exhaustive dependencies #28539

Open
arendjr opened this issue Mar 11, 2024 · 0 comments
Open
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@arendjr
Copy link

arendjr commented Mar 11, 2024

React version: 18.2

Steps To Reproduce

  1. Use the useState() hook.
    • For example: const [count, setCount] = useState(0)
  2. Create a function that directly uses the setter.
    • For example: const inc: () => setCount((count) => count + 1)
  3. Witness how the function using the setter is not required to be listed as dependency, leading to soundness issues.
    • For example:
      const incAndRemember = useCallback(() => {
        inc();
        setLast({ last: inc }); // We might be setting a stale reference here,
      }, []);                   // because `inc` doesn't need to be specified here.
  4. Behavior in other hooks will start to diverge from what was intended if we ever rely on the identity of the reference we set.

Link to code example: https://github.com/arendjr/react-unstable-handler

The current behavior

When a function inside a component (only) uses a setter of a useState() hook, that function is determined to be "stable" (non-reactive) despite its identity being unstable. Because the ESLint rule assumes the function is stable, it doesn't require it to be listed in dependency arrays, which may lead to soundness issues with other hooks, such as witnessed in the linked repository.

It appears the current behavior is in violation of the documentation regarding reactive values (https://react.dev/learn/lifecycle-of-reactive-effects#all-variables-declared-in-the-component-body-are-reactive ), which says:

All values inside the component (including props, state, and variables in your component’s body) are reactive. Any reactive value can change on a re-render, so you need to include reactive values as Effect’s dependencies.

The expected behavior

Whether a function is considered stable or not should be strictly determined by its identity.

@arendjr arendjr added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Mar 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

1 participant