If am to pass an object to a child component via the components props, does this object get cloned or does it simply pass a reference to the original object?
For example in my App.js
I am importing a JSON object ENTRY_DATA
. I am then passing that object via props to my child components (or in this case, routes). Am I saving on memory by doing this or would it be the same as if I was to import ENTRY_DATA
on each component?
import React, { Component } from 'react';
import { withRouter, Route } from 'react-router-dom'
import ENTRY_DATA from './../../entry_data.json';
import Register from '../Register/Register';
import Categories from '../Categories/Categories';
import Category from '../Category/Category';
import Entry from '../Entry/Entry';
class App extends Component {
render() {
return (
<div className="app" >
<main>
<Route exact path="/" component={Register} />
<Route exact path='/categories' render={(props) => (
<Categories {...props} categories={ENTRY_DATA} />
)}/>
<Route exact path='/categories/:category' render={(props) => (
<Category {...props} categories={ENTRY_DATA} />
)}/>
<Route exact path='/categories/:category/:entry' render={(props) => (
<Entry {...props} categories={ENTRY_DATA} />
)}/>
</main>
</div>
);
}
}
export default withRouter(App);
If ENTRY_DATA
is 5kb's, And I am passing it to 3 different components, does that mean I end up with 20kb's worth of ENTRY_DATA
or do they all reference the one 5kb ENTRY_DATA
?
In general, it depends on the data-type of said prop. Primitives, such as integers or Strings are passed down by their value, while Object data-types such as arrays are passed down by their reference.
So yes, Objects specifically are passed down by reference.
Demo:
In this demo we have two components, one parent and one child. The child takes two props, one that is the integer 1
and the other is an object with a: "foo"
.
After a short while, from the parent we change the integers value from 1
to 2
and the object from a: "foo"
to a: "bar"
. After that, we log the values of these props from the child component.
Note: This is a stateless component, so we aren't using any kind of state. We are changing the values directly, so React won't ever "know" of this change! (ssh, don't tell React!)
The output is still 1
for the integer (didn't change - passed by value), but a: "bar"
for the object (changed! - passed by reference).
const Parent = () => {
let myInt = 1;
let myObj = {a: "foo"};
setTimeout(function(){
myInt = 2;
myObj.a = "bar";
}, 500);
return <Child myInt={myInt} myObj={myObj} />;
}
const Child = ({myInt, myObj}) => {
setTimeout(function(){
console.log(myInt);
console.log(myObj);
}, 1000);
return (
<div>
<p>{myInt}</p>
<p>{JSON.stringify(myObj)}</p>
</div>
);
}
ReactDOM.render(<Parent />, document.getElementById("app"));
<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="app"></div>
Props reference to objects, in fact you can pass methods with context. Mutating props is a very bad pratice discouraged by almost every linter, when you want to mutate data coming from props is better to deep clone prop and work on cloned data.
Only a reference to the object is passed. Indeed, the transformation is pretty straightforward between jsx
/tsx
and plain old js/ts. This babel reference is a good example of this.
This means that any sort of object can potentially be sent - numbers, booleans, arrays, functions, plain old objects, DOM elements etc. It also means that if the object is mutable, it could be modified. But it should not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With