feat: automatic conversion of constants in JSX children to React.element#818
feat: automatic conversion of constants in JSX children to React.element#818anmonteiro wants to merge 1 commit intomainfrom
Conversation
jchavarri
left a comment
There was a problem hiding this comment.
Maybe this is early feedback as it's still a draft, but I am not pumped about the proposal. It doesn't follow the principle of least surprise because now the string literals will be interpreted differently by the PPX based on where they appear on the AST. I'm not sure it's a good tradeoff for the sake of saving a few keystrokes, or making ReasonReact component be more like JS ones, if those are the goals.
Also, I think it's safe to say we have a very limited idea at the moment about the impact and the amount of edge cases that will originate from this change, so if we decided to move forward, maybe we could put the new behavior under some experimental flag in the ppx so that people can opt-in to try it.
| } -> | ||
| transformChildren_ acc (mapper#expression ctxt v :: accum) | ||
| transformChildren_ acc | ||
| (mapper#expression ctxt (wrap_constant v) :: accum) |
There was a problem hiding this comment.
Below are mostly the points that Ricky already shared in reasonml/reason#1910, but I think it's good to have them here for completion.
This introduces a new "region" where things behave differently. E.g. this compiles:
module Foo = {
[@react.component]
let make = () => {
<div> "a" </div>;
};
};but this does not:
module Foo = {
[@react.component]
let make = () => {
let a = "a";
<div> a </div>;
};
};I am not sure how I feel about these "regions", it reminds me a bit of useEffect and the dependencies, which is probably no bueno 😅
| module Foo = { | ||
| [@react.component] | ||
| let make = (~id) => { | ||
| <div key=id> [|<div />, "a"|] "a" 'b' 3 false </div>; |
There was a problem hiding this comment.
What happens in the following cases?
- Child is a variant or polyvar with a string payload
- Child is a quoted string
- Child is a tuple of strings
- Child is a function application with a string param
- Child is an extension with an string payload, e.g.
[%intl "foo"], we use these a lot at Ahrefs. I particularly wonder if PPX ordering could have any impact, e.g. if the ppx processingintlgenerates a string literal, would the behavior change if it runs before or after reasonreact ppx?
There was a problem hiding this comment.
This only checks the Pconst kinds and applies the right React.string/int/float/char.
For all your cases, the type-checker will break. I would like to see the quality of the error in such cases
There was a problem hiding this comment.
For all your cases, the type-checker will break.
I think the quoted string would pass because it's also Pconst_string. But it should prob be tested as well. Actually it might be interesting to test the whole thing (including type checking) and not only the syntactic transformation.
There was a problem hiding this comment.
yeah, if we move ahead with this, proper testing is required. I just included a simple cram syntactical example to show case what the PPX desugars to.
Indeed these are the tradeoffs we knew we'd face when we first thought about this proposal. As you mentioned, it's also the main concern highlighted in reasonml/reason#1910. Let me try to offer a perspective that I don't think has been shared yet:
Now, probably the reasonable thing to do would be to gather some data of the ratio between calling How else are you thinking about the tradeoffs here? I'd be curious to learn what tradeoffs I'm missing. |
I can take this PR for a ride on Ahrefs codebase and see what % of usages of But it'd have to be after the migration to React 18 / latest reason-react, which is currently ongoing. |
|
This again proves to be not sufficient for the effects that we actually needed, which is removing most (likely all |
No description provided.