Cole
Cole

Reputation: 572

How to know where to add states in react.js

New to react and did not know how to structure a google search for this so decided to ask it here. Was taking a react tutorial and the instructor did this:

#App.js

import React, { Component } from 'react';
import Ninjas from './Ninjas.js'


class App extends Component {
  state = {
    ninjas : [
      { name: 'Ryu', age:30, belt:'black', id:1 },
      { name: 'Jacy', age:34, belt:'yellow', id:2 },
      { name: 'Ikenna', age:20, belt:'green', id:3 },
      { name: 'Cole', age:50, belt:'red', id:4 }
    ]
  }
  render() {
    return (
      <div className="App">
        <p>My First React App</p>
        <hr/>
        <Ninjas ninjas={ this.state.ninjas } />
      </div>
    );
  }
}

export default App;



#Ninjas.js

import React, { Component } from 'react';

const Ninjas = (props) => {
    const { ninjas } = props;
    const ninjaList = ninjas.map(ninja => {
      return (
        <div className="ninja" key={ ninja.id }>
          <div>Name: { ninja.name }</div>
          <div>Age: { ninja.age }</div>
          <div>Belt: { ninja.belt }</div>
          <hr/>
        </div>
      )
    })
    return(
      <div className="ninja-list">
        { ninjaList }
      </div>
    )
}

export default Ninjas

But then I tried this and it gave the same result:

#App.js

import React, { Component } from 'react';
import Ninjas from './Ninjas.js'


class App extends Component {

  render() {
    return (
      <div className="App">
        <p>My First React App</p>
        <hr/>
        <Ninjas />
      </div>
    );
  }
}

export default App;



#Ninjas.js

class Ninjas extends Component {

  state = {
    ninjas : [
      { name: 'Ryu', age:30, belt:'black', id:1 },
      { name: 'Jacy', age:34, belt:'yellow', id:2 },
      { name: 'Ikenna', age:20, belt:'green', id:3 },
      { name: 'Cole', age:50, belt:'red', id:4 }
    ]
  }

  render() {
    const ninjaList = this.state.ninjas.map(ninja => {
      return(
        <div className="ninja" key={ ninja.id }>
          <div>Name: { ninja.name }</div>
          <div>Age: { ninja.age }</div>
          <div>Belt: { ninja.belt }</div>
          <hr/>
        </div>
      )
    })
    return (
      <div className="ninja-list">
        { ninjaList }
      </div>
    )
  }
}

export default Ninjas

Why did he put the state in the parent App component and not in the nested Ninjas component? And how do you know when to pass data down as props and not use it as a state in the component that needs the data?

Upvotes: 0

Views: 80

Answers (5)

Liren Yeo
Liren Yeo

Reputation: 3451

First of all, congratulations on noticing this ;) You're 1 step closer to React Thinking

In your example, it doesn't make a difference whether ninjas state lives in App, or in <Ninjas/> component. It only matters when this app grows more complicated.


Smart Container vs Dumb Component

The tutorial example is building <Ninjas/> as a dumb/presentational component, which is why it did not use class, but was written as a Stateless Functional Component. It is merely used for displaying data in certain way.

But why? Because we might want to reuse <Ninjas/> component with different data set.

In an actual app, most likely you wouldn't hardcode the ninja's data as state. What usually happen is, a smart container (in this case, App) will make API call to backend server to retrieve all the ninja data, then save them as state.

Using the tutorial's structure, you now have the flexibility to:

  1. Pass down ninjas state to other components that might need the data. For example, a <BeltCount/> component that displays the count for each belt color. Not the best example, but the point here is reusability.

  2. <Ninjas> components can be reused as well! Now that it doesn't have any hardcoded state in it, anyone can reuse <Ninjas> by passing down different ninjas props.

Upvotes: 2

user1579234
user1579234

Reputation: 501

There are two types of components in React: Container Component and Presentation Component.

Container component is the top level component and has the information about state(and other advanced things like Redux store etc.).

Presentation component are only responsible for representing your content.

The instructor has used functional component for your 'Ninjas' class and it accepts props from the top layer. This is the standard practice in React and I would recommend to follow it. As you progress in your learning, you will better understand why only top level component needs to have the knowledge of state. Good luck!

Upvotes: 0

Ryan Cogswell
Ryan Cogswell

Reputation: 81066

With the example as is, there isn't any compelling reason for the state to be at the App level. I would expect that as the tutorial progresses and the example gets more complicated (state being changed in some manner and potentially used/displayed by multiple components), that the reasons for the state being where it is will become more clear.

Upvotes: 0

Kayote
Kayote

Reputation: 15637

I would like to answer the specific part:

how do you know when to pass data down as props and not use it as a state in the component that needs the data?

It probabaly is because the data in the state is being used / manipulated by some other elements as well. Example could be 'sort'/ 'delete' etc.

As a general rule, you should keep your state as local as possible, i.e, where the state data is being used. Think of the concept encapsulation.

Hope that helps.

Upvotes: 0

Murat Karag&#246;z
Murat Karag&#246;z

Reputation: 37604

In your second example you are passing an undefined state.ninjas it has no effect whatsoever. The reason why your second example works is because you define the state with the props from the first example.

Try to call it like in the first example with const { ninjas } = props and it won't work anymore.

The reason why you would take the first approach is that you can define an arbitrary list of ninjas while in the second one you have always the same ninjas.

Upvotes: 0

Related Questions