Lifting State in React Components
Tags: react, webdev, programming, javascript
Published: 2021-01-20 23:07:15

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we’ll look at the principle of lifting states up.

Lifting State Up
================

We should lift any shared state up to their closest common ancestor.

This way, one state can be shared between multiple child components by passing them down via props.

For example, if we want to build a calculator for converting lengths, we can write the following:

```
import React from "react";  
import ReactDOM from "react-dom";

class LengthInput extends React.Component {  
  constructor(props) {  
    super(props);  
    const { length } = this.props;  
    this.state = { length };  
  }  
  
  handleChange(e) {  
    this.props.onChange(e);  
  } 

  componentWillReceiveProps(props) {  
    const { length } = props;  
    this.setState({ length });  
  } 

  render() {  
    const { unit } = this.props;  
    return (  
      <>  
        <label>Length ({unit})</label>  
        <input  
          value={this.state.length}  
          onChange={this.handleChange.bind(this)}  
          placeholder={this.props.unit}  
        />  
        <br />  
      </>  
    );  
  }  
}

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = { lengthInMeter: 0, lengthInFeet: 0 };  
  } 

  handleMeterChange(e) {  
    this.setState({ lengthInMeter: +e.target.value });  
    this.setState({ lengthInFeet: +e.target.value \* 3.28 });  
  } 

  handleFeetChange(e) {  
    this.setState({ lengthInFeet: +e.target.value });  
    this.setState({ lengthInMeter: +e.target.value / 3.28 });  
  } 

  render() {  
    return (  
      <div className="App">  
        <LengthInput  
          length={this.state.lengthInMeter}  
          onChange={this.handleMeterChange.bind(this)}  
          unit="meter"  
        />  
        <LengthInput  
          length={this.state.lengthInFeet}  
          onChange={this.handleFeetChange.bind(this)}  
          unit="feet"  
        />  
      </div>  
    );  
  }  
}

const rootElement = document.getElementById("root");  
ReactDOM.render(<App />, rootElement);
```

In the code above, we have a length converter than converts meters to feet when we’re typing in the meters field and vice versa.

What we’re doing is that we keep the lengths all in the `App` component. This is why the principle is called lifting the states up.

Since we’re keeping the lengths in the `App` component, we have to pass them down to the `LengthInput` components.

To do that, we pass props to them. Also, we pass in the units, and the change handler functions down to our `LengthInput` components, so that they can the functions to update the states in the `App` component.

In the `handleFeetChange` and `handleMeterChange` functions, we set the state according to the values entered in the `LengthInput` components.

We call `this.setState` in both functions to set the states. Each time `setState` is called, `render` will be called, so that the latest state will be passed down to our `LengthInput` components.

In the `LengthInput` components, we have the `componentWillReceiveProps` hook which will get the latest prop values and then set the `length` state accordingly.

`this.state.length` is set as the value of the `input` elements in `LengthInput` , so the inputted value will be shown.

The advantage of lifting the states up to the parent component is that we only have to keep one copy of the state. Also, we don’t have to repeat the processing of the states in different child components.

The values of the inputs stay in sync because they’re computed from the same state.

Conclusion
==========

When writing React apps, it’s recommended that we move shared states between child components into their parent component. This is called lifting the states up.

We want to do this so that we don’t have to duplicate the processing of data in child components, and we only have a single source of truth.

To do this, we can pass in data and function as props down to child components. This way, functions from the parent component can be called from child components.

Then to update the states of child component with the latest values passed from the props, we can use the `componentWillReceiveProps` hook to update the states from the props.