Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the ordering of props in JSX important?

If the o object contains a key/value pair of: foo: 'bar' can I depend on these outcomes?:

// foo will be 'bar'
<MyComponent
    foo='should not override'
    {...o}
  />

// foo will be 'overridden'
<MyComponent
    {...o}
    foo='overridden'
  />

In other words, is the ordering of properties while using the spread operator significant?

like image 214
Jonathan.Brink Avatar asked Jun 16 '17 14:06

Jonathan.Brink


People also ask

Why is it important to avoid copying the values of props into a component's state where possible?

Anti-pattern: Unconditionally copying props to state Because of this, it has always been unsafe to unconditionally override state using either of these lifecycles. Doing so will cause state updates to be lost. At first, this component might look okay.

How props can be defined within JSX?

However, since JSX is used to express XML-like nodes that get turned into HTML, attribute/props are defined by adding the attributes/props to JSX expressions as name-value attributes. In the code example below I am defining a React <li> element node, using JSX, with five attributes/props.

Can you pass JSX as props?

Not only can JSX elements be passed as props to components, but we can also pass other components as props. In fact, there is a special type of prop that is automatically provided on the props object called children .


2 Answers

Yes, ordering does matter. The exact reason is how Babel transpiles the JSX. You can see this in the Babel REPL:

<MyComponent foo="should not override" {...o}>

</MyComponent>

Becomes:

React.createElement(MyComponent, _extends({ foo: "overridden" }, o));

Where _extends is just Object.assign, or if the browser doesn't support it, _extends is functionally the same. Per the MDN documentation:

Properties in the target object will be overwritten by properties in the sources if they have the same key. Later sources' properties will similarly overwrite earlier ones.

(Emphasis is mine). Thus, when Object.assign is used to pass props to the component, the target is { foo: "overridden" } and the source is o. Since foo exists in both the target and the source, foo in the target is overridden. This also applies to:

<MyComponent {...o} foo="overridden">

</MyComponent>

Here, the JSX is transpiled to the opposite:

React.createElement(MyComponent, _extends({}, o, { foo: "overriden" }));

It's a bit different because here, the target is an empty object, but the latter half of the quote from MDN applies. The sources here are o and { foo: "overridden" }. Since foo exists in both sources, the foo in source { foo: "overridden" } overwrite's the foo from o.

like image 177
Andrew Li Avatar answered Oct 06 '22 08:10

Andrew Li


yes, it is. It works exactly as your example says

You example is translated into:

// foo will be 'bar'
<MyComponent
    {/* ...other 'o' keys/values...*/}
    foo='should not override'
    {/* ...other 'o' keys/values...*/}
    foo='bar'
/>

// foo will be 'overridden'
<MyComponent
    foo='bar'
    {/* ...other 'o' keys/values...*/}
    foo='overridden'
    {/* ...other 'o' keys/values...*/}
/>

And therefore, it overrides always the last one

like image 27
Mayday Avatar answered Oct 06 '22 08:10

Mayday