-
Notifications
You must be signed in to change notification settings - Fork 38
JSX 4: component name when created without @react.component #695
Comments
Good catch! |
Right, but how can we support the above use case where the user wants to specify the props type himself? Could we also just add |
This is still a bit up in the air. You can use the same thing that the ppx does now, and define a capitalized quoted id. The current situation is that there isn't a nice language level mechanism to cover the complete picture, including the default export normally used by components, and capitalized name. |
The default is the more delicate aspect, so perhaps worth looking at it in isolation. Making this up as we speak. So at the language level one wants to have the notion of module with a default value, and this should map nicely to JS's notion of default export. Some implicit convention, or explicit mechanism, could be used to give the name of the module to the |
Treating inner modules and files differently is a bit of a complication, when e.g. functors are used. One can explore several things. Needless to say, this is very speculative and not for the short term for sure. |
Combining with the exploration of dynamic import // Counter.res has @react.component let default = ...
...
module C = await import(Counter)
<C .../>
... |
IMHO we should support the use case of the user specifying a (possibly shared) props type himself out of the box with the upcoming JSX 4 release. Yes, the user could do something like this manually to get the right component function name, but this is quite cumbersome: type sharedProps = {x: string}
module A = {
type props = sharedProps
let make = {
let \"A" = ({x}) => React.string("A: " ++ x)
\"A"
}
} Why can't we extend the PPX so that we can have type sharedProps = {x: string}
module A = {
type props = sharedProps
@react.component
let make = ({x}) => React.string("A: " ++ x)
} and the PPX does just the function name thing in this case? |
This is doable, probably requiring some additional annotation (e.g. an argument to |
Though I would not change the syntax, still |
What I meant was that I can already write module A = {
type props = sharedProps
let make = ({x}) => React.string("A: " ++ x)
} now and it will work without any additional attribute, except for the incorrect function name. So I wanted to add an attribute (whether the existing You are proposing something like this instead, right? module A = {
@react.component(sharedProps)
let make = (~x) => React.string("A: " ++ x)
} where the |
Using argument for |
// @react.component
module A = {
@react.component
let make = (~x, ~y) => React.string(x ++ y)
}
// @react.componentName
module B = {
type props = {x: string, y: string}
@react.componentName
let make = props => React.string(props.x ++ props.y)
}
// No attributes
module C = {
type props = {x: string, y: string}
let make = props => React.string(props.x ++ props.y)
let make = {
let \"C" = (props: props) => make(props)
\"C"
}
} |
This variation might actually work. The ReScript // Foo.res
let default = 3 Could compile to this JS: // Foo.js
let Foo = 3
export default Foo So This should respect the rule of a single capitalised export where needed. |
Nice! But then we would need to change JSX to use |
Yes a rename would be necessary. Can be done incrementally helped by config settings, in case this works out without issues. |
Actually I think this would be quite nice, as it would allow people to specify a shared props type where needed without having to change anything else in their code. One example where a shared prop type is needed is when you have an API that takes a |
I have a question regarding this example: module A = {
@react.component(sharedProps)
let make = (~x) => React.string("A: " ++ x)
} What does type sharedProps = {
x: string
} Is it? |
Yes |
Got it. Can you help me to understand what demanded usages are? If |
Yes, exactly. Use case is as described here:
E.g., React Navigation. Let's say (very simplified) you have bindings giving you a type screenProps = { navigation: navigation, route: route }
module Screen: {
@react.component
let make: (
~name: string,
~component: React.component<screenProps>,
...
) => React.element
} and you have a component @react.component
let make = (~navigation: navigation, ~route: route) => ... and want to define a screen as follows: <Screen
name="SomeScreen"
component={SomeComponent.make}
...
/> Then this won't work because the props types don't match. |
Ah! I remember this post https://forum.rescript-lang.org/t/call-for-help-2-test-jsx-v4/3781/9?u=moondaddi |
type sharedProps<'a> = …
// original
@react.component(sharedProps)
let make = (~x) => ...
// converted to
type props<'a> = sharedProps<'a> // tricky part here, when shareProps has type parameter
let make = ({x}: props<_>) => ...
let make = {
let \"Foo" = props => make(props)
\"Foo"
} I think there is a tricky part there. |
I'll grab some time to implement this feature soon. I expect that a few code changes will make this work. |
That's great! Thanks a lot! (If it turns out to be too complicated, the |
I'd like to take another issue here regarding the function component name starting with lowercase which would lead to breaking the React Fast Refresh. As @ryyppy raised: We need to consider both cases.
Can we make a sample project to see the breaking of the React Fast Refresh? Maybe we need to ask in the forum. |
@mattdamon108 It is very easy to run into troubles with Fast Refresh not working. I can create a sample project with various cases. 🙂 |
Wow! it would be great. |
But maybe we should open a separate issue for the fast refresh and default export things and close this one? As the original problem reported here is already resolved with the shared props type feature. |
The rescript-lang/syntax repo is obsolete and will be archived soon. If this issue is still relevant, please reopen in the compiler repo (https://github.com/rescript-lang/rescript-compiler) or comment here to ask for it to be moved. Thank you for your contributions. |
When using JSX 4, it is possible to create a component without
@react.component
by just creating a module with aprops
type and a functionmake: props => React.element
. This can be useful in some cases, or even required due to nominal typing if we want to ensure that multiple components share the same props type.However, if we create a component that way, its name will just be
make
. For example, when rendering the following componentit looks like this in the React Dev Tools components inspector:
The text was updated successfully, but these errors were encountered: