Correct way to use `React.forwardRef` with uncurried ReScript + ReScriptReact 0.12?

As I’ve mentioned in other threads I’m working on upgrading our rescript app from using bs-platform 9 to rescript 11. In the process I’ve upgraded us from using @rescript/react@0.10.3 to @rescript/react@0.12.1. I’m not sure which change is responsible for the difference here, but we have quite a few components in our app which we define using React.forwardRef so that they can pass refs to child components. It looks something like this

@react.component
let make = React.forwardRef((
  ~dataCy: string,
  ~className: option<string>=?,
  ~children=React.null,
  ref_,
) =>
  <Spread props={"data-cy": dataCy}>
    <div
      ref=?{ref_->Js.Nullable.toOption->Belt.Option.map(ReactDOM.Ref.domRef)}
      ?className>
      children
    </div>
  </Spread>
)

However, with the upgraded libraries, this is now giving a type error:

rescript: [6/433] src/components/DataCyDiv.cmj
FAILED: src/components/DataCyDiv.cmj

  We've found a bug for you!
  DataCyDiv

  This function expected 2 arguments, but got 1

What’s the fix for this? Since this is going through the @react.component ppx, the code it’s outputting is pretty opaque to me and I’m not sure what it’s complaining about. The binding definition in React.res looks like this

@module("react")
external forwardRef: (@uncurry ('props, Js.Nullable.t<ref<'a>>) => element) => component<'props> =
  "forwardRef"

If anyone has React.forwardRef working in an app with rescript 11 or higher, please help me out :slight_smile:

I guess you are still using JSX V3? Not sure if that is possible. @moondaddi maybe knows more.

Personally, I would use JSX V4 where that example compiles in uncurried mode: ReScript Playground

But actually, I would not use forwardRef at all, since it’s discouraged, even by the React team.

And in React 19 you will be able to just pass it as any other prop.

2 Likes

Yeah we are on JSX 3 and we’re on an older version of react which requires forwardRef (as far as I know). But it’s interesting that it’s discouraged (maybe it should be marked as deprecated and given a compiler warning?) and that it’s not necessary. Unfortunately the docs don’t suggest what to do instead. Is the correct way to just add a ~ref prop on the outer component and pass it to the inner component?

1 Like

The alternative is to Forward Refs via Props: Forwarding Refs | React
Just add a ~myWhateverRef prop that is not just named ref.

2 Likes

@adnelson Have you added “-open ReactV3” to bsc-flags in your rescript.json or bsconfig.json? rescript-compiler/docs/JSXV4.md at master · rescript-lang/rescript-compiler · GitHub

1 Like