What's the correct way to bind a React component with reserved keywords as prop names?

I have a binding for Headless UI Dialog that stopped working recently. Maybe after upgrading to Rescript 11. The generated JS now has _open instead of open and I’m not sure why. I tried underscore prefix and suffix but both failed to have any effect.

@react.component @module("@headlessui/react")
external make: (
  ~onClose: unit => unit,
  @as("open") ~_open: bool=?,
  ~children: React.element,
  ~className: string=?,
  @as("as") ~_as: string=?
) => React.element = "Dialog"

module Panel = {
  @react.component @module("@headlessui/react") @scope("Dialog")
  external make: (~children: React.element, ~className: string=?) => React.element = "Panel"
}

module Title = {
  @react.component @module("@headlessui/react") @scope("Dialog")
  external make: (~children: React.element, ~className: string=?, @as("as") ~_as: string=?) => React.element = "Title"
}

I’m not sure, what you are actually trying to ask, since your code example seems alright.

I believe name-mangling (special handling for names containing underlines at specific positions) was recently changed.
Because we have @as("name") and \"name". I added the second possibility to your example:
Example in playground

module Example = {
  @react.component @module("@headlessui/react")
  external make: (
    ~onClose: unit => unit,
    @as("open") ~open_: bool=?,
    ~children: React.element=?,
    ~className: string=?,
    ~\"as": string=?,
  ) => React.element = "Dialog"

  module Panel = {
    @react.component @module("@headlessui/react") @scope("Dialog")
    external make: (
      ~children: React.element,
      ~className: string=?,
    ) => React.element = "Panel"
  }

  module Title = {
    @react.component @module("@headlessui/react") @scope("Dialog")
    external make: (
      ~children: React.element,
      ~className: string=?,
      @as("as") ~_as: string=?,
    ) => React.element = "Title"
  }
}

let noop = () => ()

let x = <Example onClose=noop open_=true \"as"="as" />
2 Likes

That’s a breaking change in ReScript 11. The workaround is to use @as("open") as you did, although if you have JSX v3 enabled, it might not work. Try upgrading to JSX v4.

1 Like

Both fixes seem to work. I didn’t know about the quote syntax, it might be missing from the docs. The JSX setting confused me a little, but after checking the schema I learned that the JSX setting changed from "reason": {react-jsx: 3} to "jsx": {"version": 4}.

1 Like