Application State Management

By Syncfusion®, Inc. · Last updated

Shared state, state ownership, lifting state up, managing shared state, keeping parent and child in sync, where to place state, local vs global state, and choosing an approach.

Introduction to Shared State

Shared state is state that more than one component needs. For example, the number of books in the cart is shown in the header and on the cart page.

If each component keeps its own copy, the copies can show different numbers. To keep them the same, you keep one copy and share it.

Real-World Example

In a bookshop app, the header shows the cart count, the book page adds items, and the checkout page shows the total. All three read the same cart.

The cart is kept in one place: a CartProvider with useReducer. Each component sends actions such as { type: "add", book }, and every part of the page shows the same cart.

Left: two siblings each keep their own count, so they disagree. Right: the parent keeps one count and passes it to both, so they agree Each child has its own state

App

Header count = 2

CartPage count = 5 Different numbers The parent has the state

App count = 5

5

5

Header shows 5

CartPage shows 5 Same number

When two components must show the same data, keep one copy of it in their parent.

If two components must always show the same data, they must not each keep their own copy. Keep one copy, in one place.

State Ownership

Every piece of state has an owner: the one component that creates it with useState. Only the owner can change it.

Other components get the state from the owner:

  • To read it, they receive it as a prop.
  • To change it, they receive a function from the owner and call it.

This keeps one clear rule: there is one place where the data lives, and one place where it changes.

The lab below shows what goes wrong without a shared owner. Each component owns its own count.

Click the button a few times. The button's number goes up, but the badge stays at 0. Each component owns its own count, so they do not know about each other.

Lifting State Up

Lifting state up means moving the state from a child up to its parent. The parent becomes the owner. Then it passes the state down to every child that needs it.

There are three steps:

  1. Move the useState line from the child up to the parent.
  2. Pass the value down to the children as a prop.
  3. Pass a function down to the child that changes it.

Lifting state up: the state moves from a child up to the parent

App (parent) new home of the state

LikeButton

LikeCount

likes

The likes state moves up from a child to the parent. Now both children can use it.

Click the button. Now the badge changes too. App owns count. CartBadge only shows it, and AddButton only asks App to change it.

Neither child has useState any more. They are now simple components that get everything from props.

Shared State Management

Shared state management means deciding how shared state is stored, read and changed. When many children use the same state, keep these points in mind:

  • One owner — Only one component has the useState for it.
  • Read with props — Children receive the value as a prop.
  • Change with functions — Children receive functions such as onAdd or onRemove. They never change the value themselves.
  • Clear names — Name function props after the action: onAdd, onRemove, onClear.

App owns the cart. The heading, BookList and CartSummary all show the same cart, because there is only one.

Parent-Child State Synchronization

Synchronization means keeping two things the same. A parent and a child stay in sync when:

  • the parent sends the current value down as a prop, and
  • the child sends changes up by calling a function prop.

This is often used for inputs. The parent owns the text, and the child shows the input box.

Parent and child stay in sync: data goes down as props, changes go up through a function prop

App search = "hab"

SearchBox <input />

value (prop) onSearch (function)

Data flows down as props. Changes flow up when the child calls a function from the parent.

Type in the box. The list filters as you type. Now click Clear. The parent sets search to "", and the box inside the child becomes empty too. Parent and child always show the same text.

Look at this line in App:

<SearchBox value={search} onSearch={setSearch} />

value={search} sends the text down. onSearch={setSearch} gives the child a way to change it.

State Placement Strategy

Where should a piece of state live? Follow these steps:

  1. List every component that reads or changes the state.
  2. Find their closest shared parent in the component tree.
  3. Put the state there. If only one component needs it, keep it in that component.

State placement: find the closest parent shared by every component that needs the state

App

Shop cart lives here

Footer does not need it

Header needs cart

BookList needs cart

Header and BookList need the cart. Their closest shared parent is Shop, so the cart state goes there.

Do not put the state higher than it needs to be. If you put everything in App, then every change re-renders the whole app, and App becomes very long.

The lab below places each piece of state in the right spot:

  • isOpen is used only by Menu, so it stays local inside Menu.
  • cart is used by Header and BookList, so it lives in Shop, their closest shared parent.

Open the menu and add books. Opening the menu does not touch the cart, and adding a book does not touch the menu. Each state lives only where it is needed.

Keep state as low as possible, but as high as needed. Start in the component that uses it. Lift it up only when another component needs it too.

Local State Compared with Global State

  • Local state belongs to one component, or to a small group with a shared parent. Examples: the text in a search box, whether a menu is open.
  • Global state is used by many components all over the app. Examples: the logged-in user, the theme, the language, the cart.

Local state lives inside one component. Global state is shared with many components across the app Local state

SearchBox

text = "hab" used by one component Global state

user = Asha shared by many

Header

Cart

Profile

Keep state local when only one component needs it. Make it global only when many parts of the app need it.

Local stateGlobal state
Who uses itOne component, or a small groupMany components across the app
Where it livesInside the component, or its parentNear the top of the app
How it is sharedPropsContext (next lesson), or a state library
ExamplesInput text, open/closed, selected tabLogged-in user, theme, language, cart

Most state in an app is local. Only a few things are truly global.

Choosing a State Management Approach

Pick the simplest approach that works. Move to the next one only when you have a real problem.

SituationApproach
Only one component uses the stateuseState in that component
A few nearby components need itLift it up to their shared parent, and pass props
The state has many kinds of changesuseReducer in the owner
Many components far apart need itContext (next lesson)
A very big app with lots of shared dataA state library, such as Redux Toolkit or Zustand

Most apps need only useState, lifting state up, and a little context. Reach for a state library only when the app is large and these are not enough.

Common mistakes

MistakeWhat you seeFix
Two components each keep their own copy of the same dataThey show different valuesLift the state to their shared parent
A child changes a prop directlyError, or the change is lostCall a function prop from the parent
Putting all state in AppApp is huge, and every change re-renders everythingKeep state in the lowest shared parent
Copying a prop into the child's own stateThe child stops updating when the parent changesUse the prop directly
Passing setCount(count + 1) instead of a functionIt runs while rendering, and loopsPass () => setCount(count + 1)
Using global state for everythingThe code is hard to followKeep most state local

Check Yourself

Exercises

What to Remember

  • When two components need the same data, keep one copy in their closest shared parent. This is lifting state up.
  • The owner passes the value down as props, and passes functions down so children can ask for changes.
  • Keep state as low as possible. Most state is local. Use context only for truly global data.

Next: Context API