← Back to React Course | Chapter 9: State Management | Lesson 10 of 10

Global vs Local State

Local state is like a note you keep in your own pocket, while global state is like a notice pinned on the school bulletin board that everyone can see and read.

What Counts as Local State

Local state lives entirely inside one component, created with useState or useReducer, and disappears when that component unmounts. A single input's current text, or whether a dropdown is open, are classic examples — nothing outside that component needs to know or care.

Note: If you can't think of any OTHER component that would need this value, it's a strong sign it should stay local.

Warning: Local state resets every time its component unmounts and remounts — don't rely on it to persist across navigation unless that's the deliberate design.

Example: What Counts as Local State

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function SearchBox() {
  const [text, setText] = React.useState("");
  return <input value={text} onChange={e => setText(e.target.value)} />;
}
ReactDOM.createRoot(document.getElementById('root')).render(<SearchBox />);
  </script>
</body>
</html>

Lifting State Up Before Going Global

When two sibling components need to share and stay in sync on the same value, the state doesn't need to go fully global — moving it up to their closest common parent component (and passing it down as props) is often enough. This is called 'lifting state up'.

Note: Lifting state up is the natural first step; only reach for Context/Redux/Zustand once prop-passing becomes genuinely awkward across many layers.

Warning: Lifting state too far up 'just in case' (all the way to the app root) when only two nearby siblings need it adds unnecessary prop-passing through everything in between.

Example: Lifting State Up Before Going Global

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function Parent() {
  const [value, setValue] = React.useState("");
  return (
    <div>
      <input value={value} onChange={e => setValue(e.target.value)} />
      <p>Sibling sees: {value}</p>
    </div>
  );
}
ReactDOM.createRoot(document.getElementById('root')).render(<Parent />);
  </script>
</body>
</html>

When State Truly Needs to Be Global

State becomes a good candidate for global management when it's needed by many components scattered across unrelated branches of the tree — like the current logged-in user, app theme, or a shopping cart accessible from both a product page and a checkout page far apart in the component hierarchy.

Note: A useful test: if lifting state up would require passing it through five or more unrelated component layers, that's a sign to go global instead.

Warning: Going global for state used by only two nearby components adds unnecessary indirection compared to simply lifting it up.

Example: When State Truly Needs to Be Global

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
// Global: current user needed by Header, Sidebar, and Checkout,
// which don't share a close common parent.
const UserContext = React.createContext(null);
function Header() {
  const user = React.useContext(UserContext);
  return <p>Logged in as: {user || "Guest"}</p>;
}
ReactDOM.createRoot(document.getElementById('root')).render(
  <UserContext.Provider value="Asha"><Header /></UserContext.Provider>
);
  </script>
</body>
</html>
Common Mistakes
  1. Making everything global 'to be safe', which makes components harder to reuse and reason about in isolation.
  2. Making everything local when two sibling components actually need the same synchronized value.
  3. Not recognizing when state has organically become needed in multiple places and should be lifted or moved to shared state.
Chapter Summary
  • Local state lives inside one component via useState/useReducer and isn't visible outside it.
  • Global state is accessible from anywhere in the app, via Context, Redux, Zustand, or similar tools.
  • Lifting state up (moving it to a shared parent) is often enough before reaching for true global state.
  • The right default is to keep state as local as possible, only widening its scope when actually needed.
Browser Support

No React-version restriction — this is an architectural pattern, not a specific API.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.