React Hooks: Lift up / pass down state using useContext and useReducer

Introduction

This tutorial is written based on this article. Original author is Vimalraj Selvam.


I've ran into a situation where I had many child and sibling components trying to share the state between them. Earlier, I used prop to send a method to share the updated states between the components. At one point of time, the number of props kept increasing and I hated that.

Then came a context based approach to store the state in a global store and share it across. But even with the context API, you had to have a render props to consume the stored state from the global context. You will soon realise that your component becomes a nested, non-maintainable and haunting to look back.

Now this post talks about how we can leverage the latest React's hooks concepts to achieve the same with a cleaner code.

Let's first build the sample UI with some child & sibling components.

Let's UI

Add a bunch of new components inside components folder.

components/UserList.js

export default function UserList() {
  return (
    <ul>
      <li>
        <span>Vimalraj Selvam</span>
        <button type="button">Edit</button>
      </li>

      <li>
        <span>Bhuvaneswari Vimalraj</span>
        <button type="button">Edit</button>
      </li>
    </ul>
  );
}

components/AddGenderToUser.js

export default function AddGenderToUser({ username }) {
  return (
    <div>
      <h2>Add gender to {username}</h2>
      <button type="button">Add Age</button>
    </div>
  );
}

components/AddAgeToUser.js

export default function AddAgeToUser({ username }) {
  return (
    <div>
      <h2>Add Age to {username}</h2>
      <button type="button">Submit</button>
    </div>
  );
}

Then, import it inside App.js.

import UserList from './components/UserList';
import AddGenderToUser from './components/AddGenderToUser';
import AddAgeToUser from './components/AddAgeToUser';

export default function App() {
  return (
    <div className="App">
      <h1>Lift up / Pass down state</h1>

      <UserList />
      <AddGenderToUser />
      <AddAgeToUser />
    </div>
  );
}

Here I've 3 child components to parent App component: UserList, AddGenderToUser and AddAgeToUser.

This is very simple example. So don't think much about the usecase of this application.

I wanted to show the AddGenderToUser component only when the Edit button for a particular user is clicked and update the title of the of the component with selected username.

The same thing goes for AddAgeToUser component, upon clicking the Add Age button from the AddGenderToUser component.

Files
FileDirectory
  • Directorycomponents[+]
    • FileUserList.js
    • Directorypublic[+]
      • Fileindex.html
      • FileApp.js
        • Fileindex.jsentry
          • Filepackage.json
            • Filestyles.css
              export default function App() {
                return <h1>Hello world</h1>
              }