PR for syntax support of JSX spread props

Hi,

I made up the PR for the syntax support of JSX spread props. I’d like to have your thoughts and get a feedback.

3 Likes

A couple of observations about the current implementation as a ppx:

  • Currently only applies to modules defined in the same file.
  • Even in the same file it would not deal with aliasing e.g. module Foo2 = Foo then {...Foo2.bar} would not work.
  • The semantics is different than in JS (so actual props get lost if not specified in the type).
  • Normally field name resolution takes into account scope and types, and shadowing. Currently the proposal is essentially textual substitution.
1 Like

Thank you for your feedback.
Actually, I also have thought about the mentioned frustrations in the step of parsing(+ppx) can’t reach other module and shadowing. I had a same issue when I made a ppx. AFAIK, it might be available in the step of type checker.

Any good way or design to access other modules in the step of parsing(+ppx)?

Just wanted to acknowledge that there are some implementation challenges, but would not want to derail the discussion onto implementation just yet.
Curious what feedback people have about the feature itself.

1 Like

“No props spreading” is definitely one of the things that surprise people I’ve introduced to ReScript so this is very cool to see it’d be a possible feature.

Thinking about the usecases for props spread; the majority of cases I have missed using it would be with interop with a JS library that expects you to spread dom props, frameworks passing through all props, or “wrapping” another component with default props or config. Unfortunately in these cases the caveat of not being able to use another file’s records would come into play there.

I totally agree with you. The moment I really missed this feature when I use the react-hook-form. I need to pass the returned value from it to dom element.

let { register } = ReactHookForm.use()

<button {...register("name")} />

Here’s the main scenario I can think of where I like to use prop spread feature in TypeScript:

Sometimes I have multiple components in different files which all accept same type of props because they do partial updates on different parts of the same large complex object. The actual edit page component then creates a props object before the return statement and spreads it into all the child components which update parts of the complex object.

Having this in ReScript would be nice, some APIs deal with passing back n forth giant objects that I like to use this pattern for.

Thank you for your work. I have something to suggest.

Is it possible to output the following when there is an input like the following?

input:

<input type=text {...register("name")} />

output:

React.cloneElement(
  ReactDOMRe.createDOMElementVariadic("input", ~props=ReactDOMRe.domProps(~type_="text", ()), []),
  register("name"),
)

What I would suggest is to use the expression as-is. This means automating the use of cloneElement. Or does anyone have a better idea?

2 Likes

Very good idea, this will lead the more simple and cleaner jsx mapper implementation without looking up the expression, but I’m afraid of the sound type checking. Because it isn’t use domProps record.

I’ve changed the implementation for the feature of spread props support based on the more general type checking of the structural typings. RFC: More general type checking for structural typings - #75 by idkjs

I think this will bring the breaking changes behind the definition of JSX, makeProps and make.

It is still the same PR, I hope to have many feedbacks and thoughts about the implementation and needs for this feature .

1 Like

Further discussion in RFC new react ppx

Seems like the downstream threads for the new ppx somewhat lose all conversation on spread support. Any news on that front?

It doesn’t lose at all. If you use V4 + classic later, you can spread props feature for the component you’ve defined, e.g. <Foo />, not <div />. If you use V4 + automatic, then you can use the spread props for both. It is not 100% the same as the use case in js, because we’re all in the nominal type system.

2 Likes