Reputation: 572
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
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.
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:
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.
<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
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
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
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
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