React Class Component - Shared State (Lifting state up)

1 - About

To shared a state between two components, the most common operation is to move the variable up to their closest common ancestor. This is called “lifting state up”. (ie removing the local state from the descendant component and move it into its ancestor instead.)

Shared State: When we update an input, an other component should reflect the change (and vice versa)

The descendant components become “controlled”.

There should be a single “source of truth” for any data that changes in a React application. Usually, the state is first added to the component that needs it for rendering. Then, if other components also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state between different components, you should rely on the top-down data flow.

Lifting state involves writing more “boilerplate” code than two-way binding approaches, but as a benefit, it takes less work to find and isolate bugs. Since any state “lives” in some component and that component alone can change it, the surface area for bugs is greatly reduced. Additionally, you can implement any custom logic to reject or transform user input.

3 - Core Modification

Temperature is the shared state.

handleChange(e) {
    // Before: this.setState({temperature:});
    // After passing the function onTemperatureChange in the props constructor from the ancestor component

The ancestor component provides:

  • the onTemperatureChange prop
  • and the temperature prop (to replace the local temperature state).

The ancestor component will handle the change by modifying its own local state, thus re-rendering both inputs with the new values.

4 - Derived state must not be in the state: Two state one storage

When two components are related: It is enough to store the value of the most recently changed input.

For instance:

  • First State: temperature: '37', scale: 'celsius'
  • Second State: temperature: '212', scale: 'fahrenheit'

We could have stored the value of both inputs but it turns out to be unnecessary.

If something can be derived from either props or state, it probably shouldn't be in the state.

5 - Example

  • Constant:

const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit'

  • Utility Function in order to convert Celsius to Fahrenheit:

function tryConvert(temperature, convert) {
  const input = parseFloat(temperature);
  if (Number.isNaN(input)) {
    return '';
  const output = convert(input);
  const rounded = Math.round(output * 1000) / 1000;
  return rounded.toString();

function toCelsius(fahrenheit) {
  return (fahrenheit - 32) * 5 / 9;

function toFahrenheit(celsius) {
  return (celsius * 9 / 5) + 32;

  • The ancestor component

class Calculator extends React.Component {
  constructor(props) {
    this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
    this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
    this.state = {temperature: '', scale: 'c'};

  handleCelsiusChange(temperature) {
    this.setState({scale: 'c', temperature});

  handleFahrenheitChange(temperature) {
    this.setState({scale: 'f', temperature});

  render() {
    const scale = this.state.scale;
    const temperature = this.state.temperature;
    const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
    const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;

    return (
          onTemperatureChange={this.handleCelsiusChange} />
          onTemperatureChange={this.handleFahrenheitChange} />
          celsius={parseFloat(celsius)} />

  • A descendant component

class TemperatureInput extends React.Component {
  constructor(props) {
    this.handleChange = this.handleChange.bind(this);

  handleChange(e) {

  render() {
    const temperature = this.props.temperature;
    const scale = this.props.scale;
    return (
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={temperature}
               onChange={this.handleChange} />

  • An other descendant components

function BoilingVerdict(props) {
  if (props.celsius >= 100) {
    return <p>The water would boil.</p>;
  return <p>The water would not boil.</p>;

  • The rendering

  <Calculator />,

<div id="root"></div>

6 - Documentation / Reference

Data Science
Data Analysis
Data Science
Linear Algebra Mathematics

Powered by ComboStrap