rescript-association / rescript-lang.org

Official documentation website for the ReScript programming language
https://rescript-lang.org
MIT License
1.85k stars 247 forks source link

Confusion about binding to external React components #685

Open Emilios1995 opened 1 year ago

Emilios1995 commented 1 year ago

The JSX 4 migration guide describes how it's possible to write components either writing the props type manually, or using the @react.component annotation.

However, when binding to external components, I found that the only valid way of defining the bindings is with the @react.component attribute, since otherwise rendering the component results in a runtime error. Please look at this playground example.

I'm not sure whether this is a bug, but if it's expected behavior, this should at least be documented somewhere. The question is where, though. The rescript-react docs used to have a section dedicated to binding to external components, but I seems like it's not there anymore.

If it's indeed a bug, I'd be happy to move this issue to the correct repo.

mununki commented 1 year ago

How about this? Is it working?

module ButtonExternalBroken = {
  type props = { text: string }
  @module("./ReadMoreButton")
  external make: (props) => React.element = "default"
}

https://rescript-lang.org/try?version=v10.1.2&code=ALBWGcA8GEHsDsBmBLA5gCgN4AIBuBTAJ3GQQC5sAWAGmwFtYATfCgIgEMBXAF1jve7IAxq2wBfAJQAoKQHoAVNgAq7ANb5s7bABtYsVZu7ZuACw2p88IgPyNsAKQDK2WDwAOPWu3h34sQUIaJrAA7tiElsyEyPCo2ABCPLzwAKKQ3ETw7NrxhPqWUthFEeCc2tzg2DHYAEZ56vDYQkz4tCEmwiZVlX5GphpC7OAa7ZbYzCjwMXH9tTGM09iFRSHIpsZm2MAR7ELcAHTNdG4IlkYC3NE1PPj72OgA8o2J3MlpGYRZ2gBy-rn58H20iKSxBSg6lWQPX8GwGQw0CGwWUEBGwACV8OAhNE3EZRhEvJVmAx4OBLjY7DUAJ7YAAGL2StNoy2wIWiglimiafBOVngeLWwR4Wx2e0OPNO-NZsEIqkqk1uIJZUnkshkUgYjDKGgZCHemWy-wa2AAvNhMMtuFS3Bo3Hk3JUzTgMukKGTopyxMtgJrtehWPtZBj2IwALIy-C6+CsYHYfDpA3aehqFj3O2wB0SU0APnR+F2B3w2nwdDOpuwrAmXHKrCkXo1TG1CSSeoTn2yv24RrGTu9vuL-sDwbDEajMZF+bFR15Z2W8Y+X2T6go6AAfi7uG7LtMsybc8GxUWS2WzZX8Ihq9xa-X+zqW41e0UrTbsOmHeXnfOtx64l6isWjH4dRyzfR1cwAHmuV4EGzTBQP2DcAFpswPA53WmMRwNkKDkmzOt1SkbZJwOadJW4KQAKXDQzXQXdc2WcC8JBbBwKjfV2xyeoxg3E1WDMbRdFEWQmJBVj73Yr5O27RoeL4otBOwYSWRYqNjHnXj+IUpSiiw7MgA

Emilios1995 commented 1 year ago

@mununki Thanks for the correction! Your code is correct, but it still breaks for my use case—though I now have a better understanding of why that is.

Your code breaks when binding to non-function components. My use case is binding to a component created with styled-components. I'm not sure how those are implemented, but I'm getting an error saying that the component is not callable.

The error is thrown by the function call generated by the Rescript compiler when writing bindings this way, as you can see in your playground's code generated JS output.

mununki commented 1 year ago

This should be working.

module ButtonExternalBroken = {
  type props = { text: string }
  @module("./ReadMoreButton")
  external make: React.component<props> = "default"
}

This isn't really about JSX4, it's about binding React.component with props type.

https://rescript-lang.org/try?version=v10.1.2&code=ALBWGcA8GEHsDsBmBLA5gCgN4AIBuBTAJ3GQQC5sAWAGmwFtYATfCgIgEMBXAF1jve7IAxq2wBfAJQAoKQHoAVNgAq7ANb5s7bABtYsVZu7ZuACw2p88IgPyNsAKQDK2WDwAOPWu3h34sQUIaJrAA7tiElsyEyPCo2ABCPLzwAKKQ3ETw7NrxhPqWUthFEeCc2tzg2DHYAEZ56vDYQkz4tCEmwiZVlX5GphpC7OAa7ZbYzCjwMXH9tTGM09iFRSHIpsZm2MAR7ELcAHTNdG4IlkYC3NE1PPj72OgA8o2J3MlpGYRZ2gBy-rn58H20iKSxBSg6lWQPX8GwGQw0CGwWUEBGwACV8OAhNE3EZRhEvJVmAx4OBLjY7DUAJ7YAAGL2StNoy2wIWiglimiafBOVngeLWwR4Wx2e0OPNO-NZsEIqkqk1uIJZUnkshkUgYjDKGgZCHemWy-wa2AAvNhMMtuFS3Bo3Hk3JUzTgMukKGTopyxMtgJrtehWPtZBj2IwALIy-C6+CsYHYfDpA3aehqFjo-C7A5HXlnAA8dtgDoAfKbsKwJlxyqwpF6NUxtQkknqE59sr9uEaxk7vb7tPh-YHg2GI1GYyL02Ks5LuMt4x8vsn1BR0AA-F3cN2XaYSU3F4Ni-C9uhnEtl-CICvcKs1ns6xuNLtFK027D5h0l52zjceuJeoq9oz8OoJavo6xY5tcrwIIWmAgfsa4ALSFnuBzutMYg5rIEHJIW1bqlI2zjpmEp8tO-4LhoZroNuJrFssOY4SC2A5lG+otjk9RjGuJqsGY2i6KIsgMSCzF3qxXxth2jRcTxB78dggkskxUbGLO3G8XJClFBhhZAA

Emilios1995 commented 1 year ago

Ah! Yeah, the output of that looks much better. Thanks for the clarification.

Now, do you think the website should have a section dedicated to bindings to external React components? It isn't necessarily obvious.

mununki commented 1 year ago

Can you tell me what part of the current doc to go in?

mununki commented 1 year ago

The rescript-react docs used to have a section dedicated to binding to external components, but I seems like it's not there anymore.

You can still access the old version of the rescript-react doc, I just can't seem to find it, can you tell me which part you are referring to?

cristianoc commented 1 year ago

@mununki we should link this to the wider effort about revisiting bindings "using the language".

I think we need to explore, then communicate best practices.

We're currently at the stage of people saying "I've tried v11 and it's great", and can move to the next phase: documenting the new way of writing bindings.

Emilios1995 commented 1 year ago

The rescript-react docs used to have a section dedicated to binding to external components, but I seems like it's not there anymore.

You can still access the old version of the rescript-react doc, I just can't seem to find it, can you tell me which part you are referring to?

I was referring to the super old reason-react docs. Specifically, this section.

Can you tell me what part of the current doc to go in?

I think we could have a new page under the "guides" section of the rescript-react docs, called "Js Interop"

mununki commented 1 year ago

@Emilios1995 I haven't seen that reason-react doc in a long time. Apparently it had something about react component binding, which is hard to find now. Thank you for reminding me.

@cristianoc Agreed.