13

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?

Stretch0
  • 8,362
  • 13
  • 71
  • 133
  • by reference. which makes it mutable, potentially. – Dimitar Christoff Jan 11 '18 at 15:13
  • @DimitarChristoff have you got any sources to confirm this? And you say potentially mutable. You mean because in theory it could be mutated but because react makes `this.props` are read-only? – Stretch0 Jan 11 '18 at 15:22
  • Probably it's a duplicate of [this](https://stackoverflow.com/questions/26089532/why-cant-i-update-props-in-react-js) – The Reason Jan 11 '18 at 15:28
  • it is potentially mutable because it gets transpiled to whatever your target is - having non writable objects is dependent on implementation of property descriptors and polyfills (also kind of possible in old IE). but if you are passing a JSON structure (aka, an Object), your components can overwrite values of the object deep in the structure and cause side effects. You should consider Immutable.js or similar. – Dimitar Christoff Jan 11 '18 at 17:25
  • yes, if its an object, it passes the reference. – Nicholas Hamilton Dec 10 '20 at 11:51

3 Answers3

13

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>
Chris
  • 57,622
  • 19
  • 111
  • 137
4

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.

Mosè Raguzzini
  • 15,399
  • 1
  • 31
  • 43
3

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.

Horia Coman
  • 8,681
  • 2
  • 23
  • 25