DEV Community

Cover image for React Stateless and Stateful Components
Live Long & Ponder
Live Long & Ponder

Posted on

React Stateless and Stateful Components

So far I've learned a few of the basics of React, and starting to get a better grasp on State. My last post covered a little on the initial uses of state and hooks in React, but now I'm learning about how state should be updated between components so that things are done cleanly.

Stateful vs Stateless components

A stateful component is just a component that houses state, while a stateless component does not. Pretty intuitive naming there :). While one houses state and the other doesn't, both can still utilize props.
If you're unfamiliar with props the terms can get a bit confusing. Props is the name of the object that holds passed-in information about a component, while this.props is the expression used to call that information. You'll often times see props used as a way to reference other passed in data, so try and be mindful of what context you're reading about props in, as it can get a little twisted sometimes.

At first I didn't understand how the information was passed between the components, did it matter if one had state and the other didn't? Is state supposed to be passed between them? Then this statement from Codecademy.org made it all come together:

  • A React component should use props to store information that can be changed, but can only be changed by a different component.

  • A React component should use state to store information that the component itself can change.

Knowing this will arm you with the core knowledge to build stateless and stateful components correctly in React.

Parent/Child relationship

To get a better idea of how the information is passed between components, its helpful to think of the relationship between these components as Parent and Child to begin with. In this relation the parent will be handling state the child will be receiving information that can be changed by the parent component.

Lets look at the job of each of piece broadly, then show some examples.

Parent

  • Defines state
  • Defines method to update state
    • If it's a class component don't forget to bind the method to the constructor for the current instance
  • Passes method on to Child

Child

  • Receives method to update state
  • Calls method by using props
  • Which in turn calls the parent to update the state Info is updated to user

Conceptually, that all makes sense, now lets look at an example and break it down.

Example

Starting with the parent, we remember it defines state, establishes a way to change that state, and passes that long to the child.

// Parent.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Child } from './Child';

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.changeFood= this.changeFood.bind(this);
    this.state = { name: 'Steak' };
  }

    // without the function breaking down the event object, this newFood would be a full event Object 
  changeFood(newFood) {
    this.setState({
      food: newFood
    });
  }
  render() {
    return <Child food={this.state.food} onChange={this.changeFood} />
  }
}
ReactDOM.render(
    <Parent />,
    document.getElementById('app')
);
Enter fullscreen mode Exit fullscreen mode

Setting the state is accomplished within the constructor, and since this is a class component, we also use the this.chageFood.bind(this) statement for our event listener. We make sure to do this so that we don't run into an error but it has to do with Javascript binding and how this is invoked. If you'd like to take a look into an article that dives deeper into it, I found this one helpful:
FreeCodeCamp Explanation

After that, our parent establishes a way to change our state, which is done with our changeFood method. This method uses setState as a way to make an update to our state.

Now we can see in the Parent's render function, we have an attribute of food and an event listener onChange which calls will call our state setter function.

Now that we have a decent idea of what our parent handling state looks like, we'll take a look at the child component.

// child.js
import React from 'react';

export class Child extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  // takes event object as parameter, extracts the piece from the event object, and then passes the correct piece back to the original parent funciton
  handleChange(e) {
    const name = e.target.value;
    this.props.onChange(food);
  }

  render() {
    return (
      <div>
        <h1>
          My favorite food is {this.props.food}!
        </h1>
        <select id="yummy-snacks" onChange={this.handleChange}>
          <option value="Steak" >
            Steak
          </option>

          <option value="Pizza" >
            Pizza
          </option>

          <option value="Burgers">
            Burgers
          </option>

          <option value="Not Healthy Food">
            Not Healthy Food
          </option>

        </select>
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Remember, the props here in Child are used to store information that can be updated by other components but not itself.

Here the child received the state setting method from the parent, and will use this.props to call it, there's just one issue. If we just used this.props.onChange in the child, we'd run into an error because we'd be passing back an event object to be displayed while the parent is expecting a string.

That's why we have the this.handleChange method:

  handleChange(e) {
    const food= e.target.value;
    this.props.onChange(food);
  }
Enter fullscreen mode Exit fullscreen mode

This allows us to take the event object as a parameter, and pull out the value we need (food), to then pass as an argument to our onChange method.

Don't forget the ever important
this.handleChange = this.handleChange.bind(this);
since we are using a method utilizing this we need to include this within our constructor.

Now when the parent receives the information from the child (our food of choice) it can accurately update and display the new state. This is done by this method in the Parent:

  changeFood(newFood) {
    this.setState({
      food: newFood
    });
Enter fullscreen mode Exit fullscreen mode

Now whenever the user selects an option from the drop down, our app will be able to handle the change in state, and correctly render a new value. Our Child component is doing it's job, by utilizing props that are updated by the Parent. Our Parent is doing it's job by setting and updating the state, and focusing less on displaying info to the user.

Siblings

An additional way to handle this situation is by using Sibling component updates, where you would utilize one component to display the information, and one component to display a way to change the information. Meaning, one Stateful Parent, with 2 stateless Children. One stateful child would pull in the props and display it to the user, while the other would display a way to update the state.

To apply it to our example, one Child would hold the logic for the dropdown and display ways to change our food, while the other would simply display what had been selected by using the props.
This can help separate the logic and make it a little cleaner and easier to read.

Wrap up

Thanks for coming along with me on learning about Stateless vs Stateful components. Let me know what else you think I should've included, or if I got something wrong! This is just a wrap up of a topic I learned about this week and wanted to share it with you all, as well as connect with people who may be learning the same thing.


Life is a long journey of learning, and I’m just happy to be sharing my stories with you.

…Until next time =)

Top comments (4)

Collapse
 
brense profile image
Rense Bakker

Class components are really something from the past. People should treat them as a deprecated feature. In functional components (React hooks) the distinction between stateful and stateless (pure) components is not explicit anymore and that's a good thing. Pure components in class based components, made people do really weird pointless stuff, like move all state up to the parent, so they could artificially keep the child pure. It's a bad practice. React hooks doesn't have this problem. You either use state or you don't and if you're later need to handle state in a component, you just add the state and the component definition doesn't need to change.

Collapse
 
livelong_ponder profile image
Live Long & Ponder

That makes sense, thanks for the insight. I know its not best practice anymore but it at least helped me understand how things have changed and see the process for how it's handled now. I'll definitely be working on implementing best practices using Hooks based on your feedback here, thank you!

Collapse
 
brense profile image
Rense Bakker

Aye, sorry if it sounded overly negative. I didn't mean to discourage!

Thread Thread
 
livelong_ponder profile image
Live Long & Ponder

No definitely didn't! I am new to this framework so any insight into current best practices is helpful!