React - Lifting the State Up

Published on
4 mins read
––– views

Data flow in React

React supports one-way data flow, where data can travel from top to bottom but cannot travel from bottom to top. The parent component can pass data to its children, but children cannot pass data to their parents. If data were a ball, it could free-fall but could not travel upwards

In React, data flows from parent components to child components through props, and child components can only modify data via callbacks passed down from their parent components. This is known as the unidirectional data flow or one-way data binding.

Lifting up the state

Lifting up state in React means managing state at a higher level of the component tree instead of within individual child components. This technique helps with sharing state and behavior between components and promoting reusability.

What's all that mean? I hear you, let me explain.

Imagine you take two kids to a toy store with a $100 budget. You give them the choice to buy as many toys as they want, or one expensive toy, as long as they stay within the budget.

You don't want to give each child $100 because they might want to buy a single expensive toy to share or because $100 for each child would exceed the budget. On the other hand, you don't want to give them only $50 each because it might not be enough for them to buy what they really want.

The solution is to hold onto the money (their state) and let them wander around the store, discuss with each other, and explore the items. After they have decided on what to buy, they will come back to you and tell you what to buy (lifting their state up to you).

You buy the toy or toys they've chosen, and everyone is happy!

Kids (sub-components/child components), talked to each other, and you (main-component/parent) controlled what they have bought and stayed in budget. Everyone is happy, the final decision is made by team work.

This is exactly what lifting state up is all about.


Real world example

Let's say we're building a React app that lists to-do items. We have three main components, each with two sub-components. The first component displays the list of to-do items, - the second one lets users add new items, - and the third one allows users to filter the items based on certain criteria.

Now, suppose we want the TodoItem and TodoList components to share state. In that case, we would need to store the state in the Main component and pass it down to the TodoItem and TodoList components as props. The same applies to the AddForm and AddButton components, as well as the FilterForm and FilterButton components. AddForm and TodoItem components do not need to see and know each other's state.

That is why we lift-up their state just enough and store it in their main component. If we kept sub-components state at the most top level, App.jsx, all 6 sub-components would have access to each-others state. This approach is OK in small apps.

Providing the data only at the necessary places will make the app run faster, cause less problems and will be easier to debug.

Quick summary

  • In React, if you want to share state data across your application, you've got to use props, because that is the only way. The data gets passed down from parent components to their child components. Unfortunately, this means that siblings (components at the same level) can't share state with each other.

  • State can be passed top to bottom. It cannot go left to right, right to left or bottom to top. This is very important to remember!

  • State passed from parent component to children can be updated and modified by that children.

  • Passing state-setter functions from parent to child components enables child components to modify the state of their parent components.