From React Class component to Functional component with hooks

How to create a React Stateful Component?

One of the most important topic in React is state. State consists of any data the application needs to know about, that can change over time. Generally, we want our apps to respond to state changes and present an updated UI when necessary.

In the previous article, we learnt how to create Functional and Class React component. In this second episode of the series From React Class component to Functional component with hooks, we will learn how to create a Stateful React component.

Summary

Before React 16.8, the only stateful component was the class component.

The React Stateful Class Component

Let’s learn how to create it, how to pass state as prop and how to modify the state.

Create a React Stateful Class Component with this.state

There are 3 steps to create a stateful class component:

  1. Create a class component (obvious, I know). If you don’t remember how to do that, just refer to the previous article.
  2. Define the initial state in the constructor, just below the super(props) method. Don’t forget to indicate “this” before state to make the new object be correctly initialized ! In fact, the state is an object with key-value pairs, an object containing as many properties as needed. Each property must be initialized with a value.
  3. Access the state value within the return render method. It is possible to access the state value in the render method using JSX like we did to access the props in the previous article. So, it must be treated as JavaScript and wrapped in curly braces. Once again, don’t forget to indicate “this” before state.

OK, that seems to be easy to do. Just have a look to code below.

class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            propertyName : value
        }
    }
    render() {
        return (
            <div>
                <p>{ this.state.propertyName } ></p>
            </div>
        );
    }
  };

Remark: There are two more ways to access the state from the render method using a constant to call the state. This constant is declared at the top of the render method, just before the return statement. Then, call the constant in the return(). The code is more easily readable that way…

  • Second way to access the state value in the render method:
    render() {
        const propertyName = this.state.propertyName;
        return (
            <div>
                <h1>{ propertyName }</h1>
            </div>
        );
    }
  • Third way to access the state value in the render method:
    render() {
        const { propertyName } = this.state;
        return (
            <div>
                <h1>{ propertyName }</h1>
            </div>
        );
      }

Pass State as Props to a React Child Component

When a component is stateful, no other components are aware of its state. Its state is completely encapsulated, or local to that component, unless we pass state data to a child component as props.

A common pattern is to have a stateful component containing the state important to our app, that then renders child components.

The rules that must be respected are:

  • The ParentComponent must be stateful.
  • In the ParentComponent, the state property is passed in the rendered ChildComponent.
  • The ChildComponent extends the React.Component
  • The ChildComponent constructor method  contains the super(props).
  • The ChildComponent access the ParentComponent state value in the render method through the props.
class ParentComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            propertyName : value
        }
    }
    render() {
        return (
            <div>
                <ChildComponent propertyName={this.state.propertyName} />
            </div>
        )
    }
}
class ChildComponent extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div>
                <h1>Hello, { this.props.propertyName }</h1>
            </div>
        )
    }
}

Example extracted from a freeCodeCamp challenge:

class MyApp extends React.Component {
    constructor(props) {…
        this.state = {name: “CamperBot”};
    }
    render() {
        return (<div><Navbar name={this.state.name} /></div>);
    }
}
class Navbar extends React.Component {
    constructor(props) {…}
    render() {
        return (<div><h1>Hello, my name is:{this.props.name}</h1></div>);
    }
}

Remark: Handler functions or any method that’s defined on a React component can be passed to  to a child component the same way. Just replace the propertyName by the methodName.

Set State with this.setState in a React Class Component

The state can not be modify directly. React provides a method for updating component state called setState. We call the setState method within our component class like so: this.setState(), passing in an object with key-value pairs. The keys are our state properties and the values are the updated state data.

  1. In the class, between the constructor and the render methods, create a handler method.
  2. In the handler method, call the setState method. Pass the needed state property and its new value in the object.
  3. In the constructor, below the state, bind the handler method because a class method typically needs to use the this keyword so it can access properties on the class (such as state and props) inside the scope of the method.
  4. In the render method, call the handler method in an event attribute (onClick attribute, for example).
class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            propertyName : initialvalue
        };
        this.methodName = this.methodName.bind(this)
    }
    methodName() {
        this.setState({
            propertyName : newvalue
        })
    }
    render() {
        return (
            <div>
                <…  onClick={this.methodName}>
                    Text
                </…>
            </div>
        );
    }
};

Remarks:

  • If you need to have access to both state and props, pass setState a function to be sure to work on the most current values of state and props.
this.setState((state, props) => ({
    propertyName: state.propertyName + props.propsName
}));

or

this.setState((state, props) {return {
    propertyName: state.propertyName + props.propsName };
});
  • Another way to call the handler method is onClick= { () => this.methodName() }.
  • State updates through the setState method can be asynchronous (refer to the LifeCycle methods).

The React Stateful Functional Component and the hook useState

Since React 16.8 it is possible to use a functional component as a stateful component. The useState hook allow us to create a state, declare en updating function and initialize the created state. Let’s discover how to do that!

Create a React Stateful functional Component with the hook useState

  1. Import { useState } from ‘react’.
  2. Create a functional component obvious, once again,  I know). If you don’t remember how to do that, just refer to the previous article.
  3. In the component function, at the top, create a state (variable), declare the updating function (updateState, setState…), and initialize the state with useState(initialvalue). The initial value may be a number, a string, a boolean, an array or an object.
  4. It is possible to access the state value in the render method using JSX like we did to access the props in the previous article. So, it must be treated as JavaScript and wrapped in curly braces.

Modify the state with updateState in a React Functional Component

In the return of the component function, use the updateState function on an event. Pass it a calculation on the state as an argument, for example.

Example:

import { useState } from ‘react’
// …
function ComponentName() {
 const productPrice = 8;
    const [state, updateState] = useState(initialValue);
    return (
        <div >
            // …
            <div>
                Product : {productPrice}€
                <button onClick={() => updateState(state + 1)}>
                    Add
                </button>
            </div>
            <h3>Total : {productPrice * state}€</h3>
        </div>
    )
}

Remark:

In this cart example, the state could be called  « cart », the function, « updateCart » and the state initialValue could be 0.

function Cart() {
    const productPrice = 8;
    const [cart, updateCart] = useState(0);
    return (
        <div >
            // …
            <div>
                Product : {productPrice}€
                <button onClick={() => updateCart(cart + 1)}>
                    Add
                </button>
            </div>
            <h3>Total : {productPrice * cart}€</h3>
        </div>
    )
}

Remark: const [cart, updateCart] = useState(0) equals to:

const cartState = userState(0);

const cart = cartState[0];

const updtateCart = cartState[1];

Pass State as Props to a React Child Component

Don’t forget to place the useState hook in the parent component if many children components use the same state. The cart state would be place in the App.js file, for example.

The rules that must be respected are:

  • In the parent component, in the return call the child component and pass it the state and the updating function as attributes.
<ComponentName variable={variable} function={function} />
  • In the child component function, pass the state and the updating function as arguments.
function ComponentName ({variable, function} ) {
    // constants et return
}

In conclusion

So, now we know how to create a stateful  React component whatever kind of component it is.

  • Class component have a this.state object in the class constructor method. This state can be called wherever in the render().
  • Class component have handler methods which call the this.setState() method to modify the state.
  • Class component have bint handler methods called on event in the render method.
  • Functional components have a useState hook which contains the state, the updating function and the initial value. This state can be called wherever in the render() too.
  • The functional component useState updating function can be called wherever in the function component return().

In the next episode, we will toggle an element using a class component and a functional component.

comment

There is no comments. Leave the first one!

Leave a Reply

Your email address will not be published. Required fields are marked *

Haut de page