Lift state between React components

Have you ever been in the situation where you need to have state stored in component, and be able to access it in a child component, or a sibling component?

This isn’t at all unusual, and there are a wide range of answers to how to handle this, but in simple cases, we can keep things simple.

Imagine you have a value stored in state, a button to increment it, and a <div> to display it in

import React, { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };
  return (
    <div>
      <p>Current Count: {count}</p>
      <button onClick={increment}>Increment counter</button>
    </div>
  );
}

All straight forward, but what do you actually do when the span to show the count is in one component, and the button to increment it is in another?

The key is in the name of the concept: lifting state

In this next example, we have three components: Parent, CountChild and ButtonChild. The code to show the count has been moved to the CountChild, and the code for the button to is in the ButtonChild. We setup the useState hook in the parent exactly the same as we have done previously, pass the count variable as a prop to CountChild for it to display all as per normal.

The key is passing a reference to setCount to the ButtonChild that allows it to update the state that is shared

import React, { useState } from "react";

export default function Parent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <CountChild count={count} />
      <ButtonChild count={count} setCount={setCount} />
    </div>
  );
}

function CountChild({ count }) {
  return (
    <div>
      <h2>CountChild</h2>
      <div>Current Count: {count}</div>
    </div>
  );
}

function ButtonChild({ count, setCount }) {
  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <h2>ButtonChild</h2>
      <div>
        <button onClick={increment}>Increment counter</button>
      </div>
    </div>
  );
}

Join the Newsletter

Subscribe to get our latest content by email.

    We won't send you spam. Unsubscribe at any time.
    Built with ConvertKit