Extending JsxDOM.domProps

Hello,

I am currently porting some code over to a ReScript project, and in the original, the <marquee> tag is used. Now I notice that in the definitions none of the props are actually listed.

My question is: how do you extend/inject into ReScript’s existing types? I’d like to add these props myself or just dismiss the error.

hey. I’m doing this in another context. You can’t - you have to write a wrapper for jsx/react it seems.

Hey, thanks for the quick reply. A shame, how would a wrapper like this look like? I’ll toy about in the meantime, see what I can get done myself.

you can probably start by copying this code and changing JsxDOM.domProps to myProps where

type myProps = {
  ...JsxDOM.domProps,
  myProp?: string
}

There are some ongoing talks about how to make jsx more extensible in ReScript, the main reason being to use it for non-react frameworks.

Meanwhile, the easiest solution is just to extend JsxDOM.props and copy-paste the needed elements from ReactDOM.res :

module JsxDOM = {
  type domProps = {
    ...JsxDOM.domProps,
    // add your custom props here
    foo?: string,
  }
}

module ReactDOM = {
  type domProps = JsxDOM.domProps
  @module("react/jsx-runtime")
  external jsx: (string, JsxDOM.domProps) => Jsx.element = "jsx"

  @module("react/jsx-runtime")
  external jsxKeyed: (
    string,
    JsxDOM.domProps,
    ~key: string=?,
    @ignore unit,
  ) => Jsx.element = "jsx"

  @module("react/jsx-runtime")
  external jsxs: (string, JsxDOM.domProps) => Jsx.element = "jsxs"

  @module("react/jsx-runtime")
  external jsxsKeyed: (
    string,
    JsxDOM.domProps,
    ~key: string=?,
    @ignore unit,
  ) => Jsx.element = "jsxs"
}

@react.component
let make = () => {
  <marquee foo="hello" />
}

playground link

2 Likes

Thinking about to create a PR to add some standard html attributes to the props type.
Since there are two different types (ReactDOM.domProps and JsxDOM.domProps) I don’t know which one is the right one.

In the react repo, I see some deprecation warnings, but they doesn’t make sense for me.

module Props = {
  @deprecated("Please use type ReactDOM.domProps")
  type domProps = JsxDOM.domProps

  /** DEPRECATED */
  @deriving(abstract)
  @deprecated("Please use type ReactDOM.domProps")
  type props = {
    ...
  }
}

Would like to get some clarification :slight_smile:

1 Like

That merely means you should use the ones that come with the compiler directly: JsxDOM.domProps.

The PR needs to be done in the compiler repo: rescript/runtime/JsxDOM.res at master · rescript-lang/rescript · GitHub

2 Likes

There are also the action and formAction attributes extended by the React library which e.g. Next.js uses to perform RPCs as part of their server actions. I am not sure, if this also qualifies as a welcome PR.

I pasted some sample code here where I replicated the basis of this video.

Maybe someone can chime in to let me know if I am on the right track with the type definitions. I also tried to use a polymorphic variant for the actionType but hat trouble to completely unbox the value needed as input for the action attribute.

I would make the callback return promise<unit> since it’s likely the most common signature instead of 'a. The real issue comes from the input of this callback function, you can’t make its type depend on a dependency, the cleanest solution would likely to add a type formData to runtime/Dom.res, we’ll see how we swap this with the experimental WebAPI bindings in the future. Apart from that, it looks ok!

1 Like