Skip to content

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

Closed
wants to merge 3 commits into from
Closed

Conversation

tom-sherman
Copy link
Contributor

@tom-sherman tom-sherman commented Dec 19, 2021

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 hooks Likely not needed, let me know if they are
  • Tests

) => 'state = "useSyncExternalStore"

@module("react")
external useSyncExternalStoreWithServerSnapshot: (
Copy link
Contributor Author

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?

Copy link
Collaborator

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.

Copy link
Contributor Author

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 😅

Copy link
Contributor

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.

@tom-sherman tom-sherman force-pushed the react-18 branch 2 times, most recently from e6fa20a to 687c471 Compare December 20, 2021 13:04
Copy link
Collaborator

@rickyvetter rickyvetter left a 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: (
Copy link
Collaborator

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"
Copy link

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.

Copy link
Contributor Author

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 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's more frustrating about having to add the . in yourself is that the type error is not helpful at all IMO

image

Copy link
Contributor Author

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.

MoOx added a commit to MoOx/rescript-react that referenced this pull request Apr 13, 2022
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!
@tom-sherman
Copy link
Contributor Author

tom-sherman commented Jun 9, 2022

@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.

@tom-sherman tom-sherman mentioned this pull request Jun 9, 2022
@tom-sherman tom-sherman marked this pull request as ready for review June 9, 2022 14:29
}

@module("react-dom")
Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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 🙏

@hackwaly
Copy link

hackwaly commented Sep 8, 2022

What's made this PR blocked? I was waiting for react 18 binding so long!

@cristianoc
Copy link
Contributor

@cristianoc
Copy link
Contributor

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.

@cknitt
Copy link
Member

cknitt commented Sep 29, 2022

@tom-sherman Thanks a lot for your contribution! 👍

I will close this PR as we are finishing the work in #46.

@cknitt cknitt closed this Sep 29, 2022
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

Successfully merging this pull request may close these issues.

React@18 support
9 participants