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

[React 19] useState's setter function becomes arity 2 #31578

Open
davesnx opened this issue Nov 19, 2024 · 7 comments · May be fixed by #31598
Open

[React 19] useState's setter function becomes arity 2 #31578

davesnx opened this issue Nov 19, 2024 · 7 comments · May be fixed by #31598
Labels

Comments

@davesnx
Copy link

davesnx commented Nov 19, 2024

Summary

The setter from useState becomes arity 2 in React's 19.0.0-rc.1 release.

Haven't found a changelog entry (https://react.dev/blog/2024/04/25/react-19 or https://react.dev/blog/2024/04/25/react-19-upgrade-guide), neither looking at the commits, so I'm not sure if it's intentional or I might miss something here.

Demo

React's 18 setStates is arity 1 https://codesandbox.io/p/sandbox/setstate-arity-1-react-18-pfdr3h
React's 19.0.0-rc.1 setState becomes arity 2 https://codesandbox.io/p/sandbox/setstate-arity-2-issue-react-19-x3l3kd

@eps1lon
Copy link
Collaborator

eps1lon commented Nov 19, 2024

Thanks for reporting. This is due to automatic compiler optimizations. Why is this an issue?

@davesnx
Copy link
Author

davesnx commented Nov 19, 2024

In the issue mentioned, there's a work in progress for reason-react support for React 19.

We use Melange to compile Reason to JavaScript and due the fact that all reason code is curried means that we need to annotate when a function (from the JavaScript world) is uncurried (almost all JavasScript functions are).

If they are annotated with uncurry, we call the code directly since we explicitly tell the compiler to do so.

If we don't, we wrap with a small utility that checks arity (fn.length) and applies their arguments accordingly.

Since the beginning, useState wasn't annotated because functions with arity 1 can't be curried (since they only have 1 argument). Now useState became arity 2, which implies we need to explicitly annotate it as uncurried and implies a breaking change.


This is the why, and I'm aware that's a long explanation that is a bit further from React.js per se, but I opened the issue to understand it better, and I wasn't aware of any automatic optimisations in the react core itself. Can you give me some pointers so that I could understand this better? Maybe there's a way to know what kind of optimisations?

@eps1lon
Copy link
Collaborator

eps1lon commented Nov 19, 2024

So reason-react can work around this?

but I opened the issue to understand it better, and I wasn't aware of any automatic optimisations in the react core itself. Can you give me some pointers so that I could understand this better? Maybe there's a way to know what kind of optimisations?

We use Closure compiler. We used to only apply this to prod but now do to dev so Closure added another argument to avoid accessing arguments in

function dispatchSetState<S, A>(
fiber: Fiber,
queue: UpdateQueue<S, A>,
action: A,
): void {
if (__DEV__) {
if (typeof arguments[3] === 'function') {

@davesnx
Copy link
Author

davesnx commented Nov 19, 2024

So reason-react can work around this?

I'm going to have a hard time with this. From what I can observe, It might differ from your reply:

The arity on the development version (using ESM.sh) is 1, while the arity of installation via npm (and bundled for prod) is 2.

It's worth mentioning that it's the same with the seducer dispatcher, is that expected as well?

@davesnx
Copy link
Author

davesnx commented Nov 19, 2024

Does the compiler add this to avoid accessing arguments as a kind-of-a-linter mechanism for React core devs?

From the outside, it seems like a good tradeoff to use another mechanism for it and try not to "break" the arity.

@eps1lon
Copy link
Collaborator

eps1lon commented Nov 20, 2024

We don't know why Closure does this. This specific optimization was removed in later versions but updating is not trivial: #31587

@eps1lon eps1lon linked a pull request Nov 20, 2024 that will close this issue
@davesnx
Copy link
Author

davesnx commented Nov 20, 2024

Saw the PR. Thanks for the effort

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

Successfully merging a pull request may close this issue.

2 participants