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

use$ does not work with React Compiler #477

Open
vladmiller opened this issue Feb 21, 2025 · 9 comments
Open

use$ does not work with React Compiler #477

vladmiller opened this issue Feb 21, 2025 · 9 comments

Comments

@vladmiller
Copy link

Hello,

Thank you for an amazing work with legend-state.

I have noticed that v3@beta is not friendly with react-compiler.

Reproduction

pnpm vite # to start the app

It has two identical components subscribed to the same store. One component uses react-compiler, another does not.

When you click on the button, "non-react-compiled" component re-renders, and another does not.

Please let me know if you need any additional information or a help debugging it.

@jmeistrich
Copy link
Contributor

Well this is fascinating. Compiler seems to be breaking use$ but it works fine with useSelector, although they're aliases to the exact same function... I will talk to the Compiler team to get to the bottom of it.

For now you could use useSelector instead of use$, which seems to work fine.

@jmeistrich
Copy link
Contributor

Ok yes, the problem is that Compiler is currently not considering use$ as a hook:

export function isHookName(name: string): boolean {
  return /^use[A-Z0-9]/.test(name);
}

https://github.com/facebook/react/blob/22e39ea72e9d10f6634ea580aaba49c2e759ef0e/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts#L1193-L1196

So I'm going to file an issue on the react repo and see what we can do. I'll post back here with any updates.

@peterkogo
Copy link

peterkogo commented Feb 27, 2025

I cannot provide you with any data or tangible evidence for the following, so take it with a grain of salt.

I'm sensing a general distaste in the webdev community for $-notations or any custom syntactic sugar for that matter. It has been quite a bumpy ride for the dollar-notation in Svelte (used for accessing stores - will probably be removed in the next version) and especially in the React world "custom looking code" is not received very positively (completely anecdotal).

I believe, people might think that there is some functionality attached to the $ and be put off by this amazing library because it looks different than your regular React code - even though it practically is.

Anyway, I love this library keep up the great work. I'll see myself out.

@jmeistrich
Copy link
Contributor

@peterkogo and others: is there a hook name that you think would be better than use$? I had perceived that many people were confused about what useSelector meant, which was the reason for the change. But if it's going to break compatibility with Compiler we need to change it, and even if Compiler decides to support it (because it's a valid JavaScript function name) maybe we can do better anyway?

My current favorite alternative ideas:

  • useGet
  • useValue$
  • useTracked
  • useSubscribe

@ievolution
Copy link

Hi, @jmeistrich, I can't thank you enough for your amazing work on Legend-State and and Legend-List!

Regarding the hook name, here are a few thoughts:

  • useGet: It’s a solid option, but it might come off as a bit too generic and may not fully capture the reactive nature of the hook.
  • useValue$: clearly signals an observable value, though it might feel a bit unconventional in a typical React context.
  • useSubscribe: does highlight the subscription aspect, yet it might not fully convey that the hook also computes or derives a value from the observable.
  • useReactiveValue: I like this one as it highlights that the returned value is both reactive and memoized, updating only when its observables change.
  • useWatched: This suggests that the hook “watches” specific parts of the state and only re-renders when those parts are updated, which is a nice touch.
  • useTracked: I think this is a great choice. It not only implies that the hook is actively observing and updating (tracking) changes, but it also aligns well with the behavior described in the documentation and reflects the idea behind useSelector.

Once again, thank you for everything you’re doing—it truly makes a difference!

@vladmiller
Copy link
Author

I saw in several codebases that people often use $ to indicate that whatever variable is an observable. And I am personally is totally fine with use$(...).

But frankly, this feels like choosing between potato and potato. It's always possible to re-export the hook with a different name.

If there is still an option, I'd say useLegendary :D

Image

@iamtommcc
Copy link

useWatched, useTracked or useValue are all good options (useValue being my favourite, it's marginally shorter and feels like the meat-and-potatoes building block that it's intended to be).

@peterkogo
Copy link

peterkogo commented Mar 1, 2025

  • useGet and useValue$ are short. Otherwise the naming does not entail what they are doing. $ reads like a S.
  • useValue, useReactiveValue 'value' adds a touch of "atomic value" which might be imprecise. (It can also be a deeply tracked object)
  • useWatched, useSubscribe and useTracked all good.

useTracked is however my favorite. Whatever function you pass in there is evaluated in "tracked" context. Tracking seems to be the word signal libraries landed on to describe the context in which subscriptions through calling getters are actually considered. Both Svelte and SolidJS make use of this word.

It would also make the documentation for this function clearer with adopting the idea of 'tracking context' instead of differentiating between observables & computation functions.

Makes the way it works together with useObservable clearer, too. From the current documentation:

Its observables will not be automatically tracked for re-rendering, so you can track them the same as any other observable.

It returns an untracked observable. Though, it can be tracked via useTracked 😏

@sshrshnv
Copy link

sshrshnv commented Mar 1, 2025

observable -> create
useObservable -> useStore
use$ -> useStored

observable -> createStore
useObservable -> useLocalStore
use$ -> useStore

or better:

observable -> createObservable
useObservable -> useCreateObservable
use$ -> useObservable

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

No branches or pull requests

6 participants