Skip to content
This repository has been archived by the owner on Jun 15, 2023. It is now read-only.

Fix react comp key type #693

Merged
merged 11 commits into from
Oct 23, 2022
Merged

Fix react comp key type #693

merged 11 commits into from
Oct 23, 2022

Conversation

mununki
Copy link
Member

@mununki mununki commented Oct 21, 2022

Copy link
Contributor

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • add a line to the changelog
  • how about JSXV4.md, does it need updating?
  • how about adding an example with ?key

@@ -36,4 +36,4 @@ module Foo = {
external component: React.componentLike<props<int, string>, React.element> = "component"
}

let t = React.jsx(Foo.component, {a: 1, b: "1"})
let t = React.jsxWithKey(Foo.component, {a: 1, b: "1"})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why jsxWithKey if the key is not passed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -167,7 +167,10 @@ module V4A = {
"div",
{
children: ?ReactDOM.someElement(
React.jsx(FancyInput.make, {ref: input, children: {React.string("Click to focus")}}),
React.jsxWithKey(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why jsxWithKey if the key is not passed?

@@ -19,7 +19,7 @@ let c2 = React.createElement(A.make, {...p, x: "x"})
// let c0 = <A x="x" {...p0} {...p1} />

// only spread props
let c1 = React.jsx(A.make, p)
let c1 = React.jsxWithKey(A.make, p)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why jsxWithKey is the key is not passed?


// reversed order
let c2 = React.jsx(A.make, {...p, x: "x"})
let c2 = React.jsxWithKey(A.make, {...p, x: "x"})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why jsxWithKey is the key is not passed?

@mununki
Copy link
Member Author

mununki commented Oct 22, 2022

@cristianoc I think I'm done with this PR including:

  • making key type an optional arg of React binding for both classic and automatic
  • updating v4 spec with example

Copy link
Contributor

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

  • Would you add an example with <Foo ?key/>
  • Update the changelog

cli/JSXV4.md Outdated

<Comp x key=?Some("7")>
// is transformed to
React.createElement(Comp.make, Jsx.addKeyProp(~key=?Some("7"), {x: x}))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it React.addKeyProp as per rescript-lang/rescript-react#74?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I'll fix it.

@cknitt
Copy link
Member

cknitt commented Oct 22, 2022

Also, I was just wondering about the following:

In

addKeyProp(~key="42", {a: a, b: b /* and maybe many more props */})

we are creating the props object, it is not passed from outside. So why do we need to use Obj.assign to create a copy of it instead of just mutating it?

@mununki
Copy link
Member Author

mununki commented Oct 22, 2022

  • Would you add an example with <Foo ?key/>

Do you mean examples in the spec? or test?

@cristianoc
Copy link
Contributor

  • Would you add an example with <Foo ?key/>

Do you mean examples in the spec? or test?

test

@mununki
Copy link
Member Author

mununki commented Oct 22, 2022

Also, I was just wondering about the following:

In

addKeyProp(~key="42", {a: a, b: b /* and maybe many more props */})

we are creating the props object, it is not passed from outside. So why do we need to use Obj.assign to create a copy of it instead of just mutating it?

Not sure I understand what you mean.
I think using Obj.assign inline would be a little verbose and more tricky to annotate type to put some magic on it. The props type doesn't have a key field, but it has to check the key type and manipulate it.

Copy link
Contributor

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
@mattdamon108 does everything work with your project?

@cristianoc cristianoc added this to the v10.1 "The New Features" milestone Oct 22, 2022
@cristianoc
Copy link
Contributor

Also, I was just wondering about the following:

In

addKeyProp(~key="42", {a: a, b: b /* and maybe many more props */})

we are creating the props object, it is not passed from outside. So why do we need to use Obj.assign to create a copy of it instead of just mutating it?

The mechanism used does 2 things:

  • type checks the normal props and generates the record value for them
  • gets around the type checker for key, so it does not have to be part of the user-visible prop type definition, and extends the record in the generated code

Even though possible in principle, I'm not sure that both are possible at the same time currently, short of creating some new primitive with special runtime support.

@cristianoc
Copy link
Contributor

Oh maybe the question is only about imperatively adding the key property. That should be OK.

@cknitt
Copy link
Member

cknitt commented Oct 22, 2022

Yes, I meant that Obj.assign is unnecessarily copying the props object, and that we could just do

(props->Obj.magic)["key"] = key

instead.

@mununki
Copy link
Member Author

mununki commented Oct 23, 2022

Looks good to me. @mattdamon108 does everything work with your project?

Now I tested v3 and v4 classic & automatic, it works fine!

@mununki
Copy link
Member Author

mununki commented Oct 23, 2022

Yes, I meant that Obj.assign is unnecessarily copying the props object, and that we could just do

(props->Obj.magic)["key"] = key

instead.

Maybe this? rescript-lang/rescript-react@2f48356

@mununki
Copy link
Member Author

mununki commented Oct 23, 2022

Yes, I meant that Obj.assign is unnecessarily copying the props object, and that we could just do

(props->Obj.magic)["key"] = key

instead.

Maybe this? rescript-lang/rescript-react@2f48356

It also works fine on tests.

@mununki
Copy link
Member Author

mununki commented Oct 23, 2022

One impressive thing is that I don't need to change the existing codes between v3 and v4 classic and automatic, except for the Context provider component in my company code base which is a quite large project.
https://github.com/rescript-lang/syntax/blob/master/cli/JSXV4.md#reactcontext

@cristianoc cristianoc merged commit eb059d4 into master Oct 23, 2022
@cristianoc cristianoc deleted the fix-key-type branch October 23, 2022 06:08
@cknitt
Copy link
Member

cknitt commented Oct 23, 2022

Yes, I meant that Obj.assign is unnecessarily copying the props object, and that we could just do

(props->Obj.magic)["key"] = key

instead.

Maybe this? rescript-lang/rescript-react@2f48356

It also works fine on tests.

We need to ensure that we do not mutate objects passed from user code. So if we do the mutation in createElementWithKey and createElementVariadicWithKey then we should document that these functions are for use by the PPX only and not meant to be called from user code.

Also, what happens in the case

<A {...props} key />

? Is props copied before being mutated or just passed through?

@cknitt
Copy link
Member

cknitt commented Oct 23, 2022

Are there no tests for createElementVariadicWithKey?

@cristianoc
Copy link
Contributor

@mununki
Copy link
Member Author

mununki commented Oct 23, 2022

Yes, I meant that Obj.assign is unnecessarily copying the props object, and that we could just do

(props->Obj.magic)["key"] = key

instead.

Maybe this? rescript-lang/rescript-react@2f48356

It also works fine on tests.

We need to ensure that we do not mutate objects passed from user code. So if we do the mutation in createElementWithKey and createElementVariadicWithKey then we should document that these functions are for use by the PPX only and not meant to be called from user code.

Also, what happens in the case

<A {...props} key />

? Is props copied before being mutated or just passed through?

This is a very good point. <A {...props} key /> would manipulate the usrs' props object.

@mununki
Copy link
Member Author

mununki commented Oct 23, 2022

@cknitt Can you move this topic to rescript-react? rescript-lang/rescript-react#74

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Breaking change of key type
3 participants