Comments

Stateful and Stateless Components in React

React logo

Stateful and Stateless Components

Today, we’re going to review what stateful and stateless components are in React, how you can tell the difference, and the complex process of deciding whether to make components stateful or not.

State Review

First, let’s review what state is.

In a component, state is data we import — typically to show the user — that is subject to change. It could change because the database we’re getting from may be updated, the user modified it — there are so many reasons that data changes!

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>
    )
  }
}

Typically we would also have a componentDidMount() that would grab our data from a database, but the above example should give you a basic idea: we have state, and we can render things from state.

Stateful and Stateless Components

Stateful and stateless components have many different names.

They are also known as:

– Container vs Presentational 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:

class Main extends Component {
 constructor() {
   super()
   this.state = {
     books: []
   }
 }
 render() {
   <BooksList books={this.state.books} />
 }
}

Stateless/Presentational/Dumb component:

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!

When should I make a component stateful or stateless?

You probably won’t know exactly how a component will turn out as soon as you start writing one — you will figure it out as you go, following some guidelines. Here are some good ones:

  1. Type out or visualize your website as if it were one component. Busy, right? Break it down from there into smaller components.
  2. You’ll need state somewhere when information dynamically changes, like a user’s current favorite songs or top scores.  Aim to have a parent component keep all the information, and pass it down to its children stateless components.
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 (no pun intended).

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.

If information is completely static and you know it will never change, we have a very ‘presentational’ component indeed. This is like a unicorn presentational component:

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>
  )
}

This stateless component doesn’t even take props! It’s always nice when this happens, but you should generally expect to have child components ready to display input via props.

Examples of stateless components being reusable

You won’t reuse every single stateless/presentational component, even though you should build in React so your components are as reusable as possible.

For example, maybe your main page has four sections, and you know you’re not going to reuse any of its components.

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>
    )
  }
}

So what would a reusable component look like?

You could have a certain way to break down CSS-designed lists that you want to reuse.

const List = props => {
  return (
    <div>
      <div className="coolHeader">{props.title}</div>
      <ul>
        {props.list.map(listItem => {
          <li className="coolListItem"}>{listItem}</li>
        })
      </ul>
    </div>
  )
}

See how that component reliably outputs whatever we pass down to it via props? Our parent component’s render function would contain the List components like so:

render() {
  return (
    <div>
      <List title=“My Favorite Shoes” list={this.state.favoriteShoes} />
      <List title=“My Favorite Animals” list={this.state.favoriteAnimals} />
      <List title=“My Favorite Websites” list={this.state.favoriteWebsites} />
    </div>
  )
}

Ahh… stateless components as they were meant to be used! Reusable-y!!!

Can stateful components be reusable?

Certainly, stateful components can be reused.

For example, a form that takes text input. No need for the parent to keep track of that. Parent components holding state should be like the motherboard of state, where only essential ‘states’ are kept track of. (More on this in the next chapter!)

But after you’ve written or thought up a schema of components, you want to figure out how you can keep the number of components holding state to a minimum, so it’s easier to keep track of state. If you’re reusing stateful components, there’s a chance you could do less work, and have a neater codebase. Ask yourself…

  1. Which of these child components can have its parent hold state instead, so the child component can just receive state as props?
  2. Are there a lot of components keeping track of state, when my life could be simplified?
  3. How else can I minimize the number of components holding state?
  4. And the worst question of all: Is there any data that is useful for a child component to keep track of using state, with no parental assistance?

Did you get to the last question? Is it blasphemy? Not at all! Here is when stateful child components come in handy:

Instances when a child component should keep track of its own state (sorry, parent component!)

There are definitely instances when a child component would be more apt to keep track of its own state, even when a parent could!

Generally, this occurs when:

  1. the data is necessary but not a major theme of your project
  2. it is user-created data that the user may later ‘submit’

One example would be a form the user is submitting.

With forms in React, we need to keep track of what the user is typing. But is it really data we need the parent component to be holding in state?

Here is a reusable component managing its own state:

class TypeStuffIn extends Component {
  constructor() {
    super()
    this.state = {
      input: []
    }
    this.handleChange = this.handleChange.bind(this)
  }
  handleChange() {
    this.setState({
      [event.target.name]: event.target.value 
    })
  }
  render() {
    return (
      <div>
        <input type=“text” name=“input” value={this.state.input} onChange={this.handleChange} />
     </div>
    )
  }
}

Something the user is typing in isn’t exactly something you want to keep track of in your parent component’s state. There’re probably more interesting things you want to keep track of in a parent component, like data your user requested, versus every single line of the user’s address as they make a purchase. For aesthetic and neatness purposes, state like that is perfectly viable to keep in the child component. Your boss will see that and be like “oh yeah, that’s boring — good move.”

Review

We covered so much! Today we learned:

  • What state actually is — data we hold that we’re aware is subject to change
  • The literal difference between stateful and stateless components
  • When you would make a component stateful or stateless — and now you know, it’s a matter of beginning to type your code and figuring it out as you go, keeping in mind you want parent components to hold as much of the state as possible, while passing down data via props to reusable children components
  • The importance of keeping components as stateless and reusable as possible
  • Sometimes, it’s very appropriate for a child component to manage state when it doesn’t have to (if the information is miscellaneous or not integral to your project’s theme)
  • Components can be reusable and have state!

It’s a lot to keep track of, but this all becomes intuitive with practice. I hope you’re feeling more confident with all things stateful, stateless and stately! If you’re ready to delve deeper into React, check out Mosh’s React course.

Francisco is a software engineer based in New York City.
Tags: ,

2 responses to “Stateful and Stateless Components in React”

  1. DHULFIQAR JASIM says:

    thank you <3

  2. rleogm says:

    Thanks , great explanation. Got me clear on this concepts.

Leave a Reply

Connect with Me
  • Categories
  • Popular Posts