ref – https://programmingwithmosh.com/javascript/stateful-stateless-components-react/
In a component, state is data we import — typically to show the user — that is subject to change.
Here we have a component Pigeon with a state object that has property pigeons. It is simply an array of pigeons that gets displayed in render. We have state, and we can render things from state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import React, {Component} from 'react' class Pigeons extends Component { constructor() { super() this.state = { pigeons: [] } } render() { return ( <div> <p>Look at all the pigeons spotted today!</p> <ul> {this.state.pigeons.map(pigeonURL => { return <li><img src={pigeonURL} /></li> })} </ul> </div> ) } } |
Also called:
Container vs Presentation components
Smart vs Dumb components.
The literal difference is that one has state, and the other doesn’t.
That means the stateful components are keeping track of changing data, while stateless components print out what is given to them via props, or they always render the same thing.
Stateful/Container/Smart component
1 2 3 4 5 6 7 8 9 10 11 |
class Main extends Component { constructor() { super() this.state = { books: [] } } render() { <BooksList books={this.state.books} /> } } |
Stateless/Presentational/Dumb component
1 2 3 4 5 6 7 8 9 |
const BooksList = ({books}) => { return ( <ul> {books.map(book => { return <li>book</li> })} </ul> ) } |
Notice the stateless component is written as a function. As cool as state is, you should always aim to make your components as simple and stateless as possible, so different components can be reused like Lego pieces, even if you don’t have immediate plans to reuse a component. The stateful ones should feel lucky to be so!
Structuring components
Aim to have a parent component keep all the information, and pass it down to its children stateless components.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class Parent extends Component { constructor() { super() this.state = { books: [], favoriteAuthors: [] } } render() { return ( <div> <Books books={this.state.books} /> <FavoriteAuthors favoriteAuthors={this.state.favoriteAuthors} /> </div> ) } } |
Doesn’t that look and feel so neat? Having a parent component pass data down to its children also assures that if there is any debugging needed regarding state management, we can go to the parent component to see what’s up, instead of checking state in each child component. All the children components have to worry about is receiving the information as props properly.
So presentational components can vary depending on what information it receives. The difference is that a stateful component keeps track of the information itself, instead of just taking it via props and outputting it.
We can also have components that render static state:
1 2 3 4 5 6 7 8 9 10 11 |
const Rules = () => { return ( <div> <p>The rules are simple and unchanging:</p> <ol> <li>You don’t talk about the rules.</li> <li>You must follow the first rule.</li> </ol> </div> ) } |
Generally, child components render UI and have no state.
Creating reusable component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Main extends Component { constructor() { super() this.state = { currentUser: {}, gamesAll: [], gamesMostPopular: [] } } render() { return ( <div> <p>Welcome, {this.state.currentUser}!</p> <AllGames allGames={this.state.gamesAll} /> <MostPopular mostPopular={this.state.gamesMostPopular} /> </div> ) } } |
Create a stateless reusable component like so:
1 2 3 4 5 6 7 8 9 10 11 12 |
const List = props => { return ( <div> <div className="coolHeader">{props.title}</div> <ul> {props.list.map(listItem => { <li className="coolListItem"}>{listItem}</li> }) </ul> </div> ) } |
then use it like so:
1 2 3 4 5 6 7 8 9 |
render() { return ( <div> <List title=“All games” list={this.state.gamesAll} /> <List title=“Most popular games” list={this.state.gamesMostPopular} /> </div> ) } |