-
Notifications
You must be signed in to change notification settings - Fork 42
React 18 support #35
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 18 support #35
Conversation
) => 'state = "useSyncExternalStore" | ||
|
||
@module("react") | ||
external useSyncExternalStoreWithServerSnapshot: ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can bikeshed the name, it's a tricky one. The alternative could be to name the parameters so that we can have getServerSnapshot
be optional so it doesn't need to passed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting to me because there are a bunch of potential future arguments - useSyncExternalStoreWithSelector in the discussion gets wildly long and adding an option to get named optional arguments means it could break in the future if those args get upstreamed into the React export. I think your naming make sense and is probably the safest way to work with these at least until there's more stability for 18 and we see how folks actually use this hook.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think one option could even be to leave the uSES hooks out for the time being. These hooks I expect to not be very prevalent at all in userland code, but I could be wrong 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd name the arguments, as there are two unit => 'state
callbacks.
e6fa20a
to
687c471
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all of this! I think this looks really good - I want to do some more testing and think a lot of this should probably be duplicated into the Uncurried sub-module for consistency. But will merge soon.
) => 'state = "useSyncExternalStore" | ||
|
||
@module("react") | ||
external useSyncExternalStoreWithServerSnapshot: ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting to me because there are a bunch of potential future arguments - useSyncExternalStoreWithSelector in the discussion gets wildly long and adding an option to get named optional arguments means it could break in the future if those args get upstreamed into the React export. I think your naming make sense and is probably the safest way to work with these at least until there's more stability for 18 and we see how folks actually use this hook.
src/React.res
Outdated
|
||
@module("useDeferredValue") external useDeferredValue: 'value => 'value = "useDeferredValue" | ||
|
||
@module("react") external useTransition: unit => (bool, @uncurry (unit => unit)) = "useTransition" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be something like:
@module("react")
external useTransition: unit => (bool, @uncurry ((unit => unit) => unit)) = "useTransition"
...?
I've noticed that @uncurry
here does not actually uncurry the startTransition function, and that's a problem because startTransition does not work if called via the curry helpers of ReScript in the officially released React 18 (it used to work up until rc-0 I think, but then broke).
@rickyvetter (or anyone else) - do you have any insight/idea about this? Would be great to not have to explicitly uncurry each startTransition call, but maybe that's our only option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your suggested type is correct, will update.
The uncurry thing feels like a bug in ReScript tbh 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TheSpyder informed me on discord that @uncurry
in this position has no affect 😕
The only way to support useTransition
without manually uncurrying would be to add a helper function:
module Transition: {
type t
let isPending: t => bool
let startTransition: (t, unit => unit) => unit
} = {
type t = (bool, (. unit => unit) => unit)
let isPending = transition =>
switch transition {
| (pending, _) => pending
}
let startTransition = ((_, start), fn) => start(. fn)
}
@module("react")
external useTransition: unit => Transition.t = "useTransition"
// Usage:
let {isPending, startTransition} = module(Transition)
let transition = useTransition()
let _ = transition->isPending
transition->startTransition(() => {
Js.log("transition")
()
})
I'm not a fan of this tbh, it's pretty unprecedented in the API of these bindings and it's zero cost. I'm going to go ahead with the manual uncurried version for now.
Currently even if there is a WIP for full React 18 support in rescript-lang#35, the package is compatible with this version range. Not having this can be a pain with "recent" version of npm (7+, which is out for a while now). Could we have this released as a fix? Thanks!
@rickyvetter I think the only blocker on merging this is #35 (comment) - would you agree? Also what do you think about removing the useSES bindings for now? And shall we do uncurried bindings in a followup? Just so that #46 is unblocked. |
} | ||
|
||
@module("react-dom") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be react-dom/client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cknitt I addressed this in the followup PR #46 which has been sitting in limbo for 2 months. I suggest we merge this PR and then open #46 for review, or maybe @tom-sherman can "steal" the commits in #46 and include them in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whatever works, just need a maintainer to get the ball rolling!
@rickyvetter Pls 🙏
What's made this PR blocked? I was waiting for react 18 binding so long! |
Seems like a good place for this to go. |
The issue is currently there's nobody specifically maintaining rescript-react per se. So pinging from time to time, as @hackwaly just did, could help things move along. |
@tom-sherman Thanks a lot for your contribution! 👍 I will close this PR as we are finishing the work in #46. |
Closes #34
This PR includes a small amount of formatting in
src/React.res
, I can remove that commit if #36 is merged first.Marked as draft until React 18 is released.
useSyncExternalStore
Uncurried version of hooksLikely not needed, let me know if they are