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]: hook-use-state reports when setter is not destructured #3871

Open
2 tasks done
AndrewBoklashko opened this issue Jan 5, 2025 · 3 comments
Open
2 tasks done
Labels

Comments

@AndrewBoklashko
Copy link

Is there an existing issue for this?

  • I have searched the existing issues and my issue is unique
  • My issue appears in the command-line and not only in the text editor

Description Overview

Sometimes it's necessary to initialize value but never update it. To get a ref-like behavior with more convinient API.

The following code:

const [eventBus] = useState(() => new EventEmitter());

Produces a warning when react/hook-use-state rule is enabled:
Image

Expected Behavior

I acknowledge that this is kind of controvercial because currently it also protects from forgetting a setter. Thus I suggest this behavior to be configurable. Furthermore, config can be done in 2 ways:

  1. opt-in: add allowMissingSetter - boolean(default false)
  2. opt-out: setterIgnorePattern - RegExp that will allow to opt-out of setter check. This is similar to ESLint's no-unused-vars varsIgnorePattern config.

I prefer solution 2 as it's not only more flexible and consistent but also protects from missing setter. The code above could be rewritten as:

const [eventBus, _] = useState(() => new EventEmitter());

This way it explicitly means: I don't need a setter.

eslint-plugin-react version

7.37.3

eslint version

8.57.0

node version

20

@ljharb
Copy link
Member

ljharb commented Jan 6, 2025

It seems pretty strange to me to have state that you never change. Is there a reason you're not using useMemo for this?

@AndrewBoklashko
Copy link
Author

Yes, from React docs:

However, since useMemo is performance optimization, not a semantic guarantee, React may throw away the cached value if there is a specific reason to do that.

In my example that state variable is used to hold a complex state object - EventEmitter(in other cases it could be e.g. a props-bounded store instance). It is important for EventEmitter instance to never re-initialize since it may lead to lost events, broken subscriptions etc. for a components that uses it.

Also inspired by blog post: useState for one-time initializations

@ljharb
Copy link
Member

ljharb commented Jan 6, 2025

Makes sense. In that case, I think the two choices here are:

  1. you can use an eslint override comment, since this use case is presumably rare
  2. we can add an option to the rule (your option 1 above)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants