Is the ordering of props in JSX important?
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
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
.
Check out this sandboxed proof:
https://codesandbox.io/s/Q1GMx9KM9
As you can see it behaves exactly as you theorized in your question.
EDITSO Snippet:
class MyComponent extends React.Component { render() { return <div>{this.props.foo}</div> }}const styles = { fontFamily: 'sans-serif', textAlign: 'center',};const o = { foo: 'bar' };const App = () => <div style={styles}> <h2>Spreading after explicit property</h2> <MyComponent foo="will be overriden" {...o} /> <h2>Spreading before explicit property</h2> <MyComponent {...o} foo="was overriden" /> </div>;ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script><div id="root"></div>