# Lifting State Up – Sharing State Between Components

As React applications become bigger, components rarely work completely independently.

Imagine a product page:

```text
                App
                 │
        ┌────────┴────────┐
        ↓                 ↓
   ProductInfo        CartSummary
        │                 │
        └─────── ? ───────┘
```

Suppose `ProductInfo` knows that a product has been added to the cart.

But `CartSummary` also needs to know.

Where should the state live?

If both components maintain their own separate state, they can easily become inconsistent.

React provides a pattern for this:

# **Lifting State Up**

We move the shared state to their closest common parent.

```text
              Parent
             /      \
            ↓        ↓
        Child A    Child B
            ↑        ↑
          shared state
```

Today we'll understand how this works and why it is one of the most important patterns in React.

* * *

# 🧠 What Does "Lifting State Up" Mean?

Suppose we have two components:

```jsx
<TemperatureInput />
<TemperatureDisplay />
```

Both need to know the same temperature.

Instead of storing temperature independently in both components, we store it in their parent:

```jsx
function App() {
  const [temperature, setTemperature] = useState("");

  return (
    <>
      <TemperatureInput
        temperature={temperature}
        setTemperature={setTemperature}
      />

      <TemperatureDisplay
        temperature={temperature}
      />
    </>
  );
}
```

The state has been **lifted up** from the child components into their common parent.

* * *

# 🤔 Why Do We Need This?

Imagine two components:

```text
Component A
    ↓
count = 5

Component B
    ↓
count = 10
```

They are supposed to represent the same information.

That's a problem.

We want:

```text
        Parent State
             ↓
       count = 5
         ↙     ↘
        ↓       ↓
   Component A Component B
```

Now both components receive the same source of truth.

* * *

# 🎯 The Single Source of Truth

One of the most important ideas behind lifting state is:

> **There should be one authoritative place where a particular piece of shared state is stored.**

For example:

```jsx
const [count, setCount] = useState(0);
```

The parent owns the state.

Children receive what they need through props.

```text
Parent
 │
 ├── state
 │
 ├── ↓ value
 │
 └── ↓ event handler
      │
      ├── Child A
      └── Child B
```

* * *

# 🔄 State Flows Down

React follows one-way data flow.

If the parent has:

```jsx
const [count, setCount] = useState(0);
```

it can pass the value down:

```jsx
<Child count={count} />
```

The child receives:

```jsx
function Child({ count }) {
  return <p>{count}</p>;
}
```

So:

```text
Parent State
     ↓
Props
     ↓
Child
```

* * *

# 🔁 But How Does the Child Update Parent State?

This is where it gets interesting.

The child doesn't directly modify the parent's state.

Instead, the parent passes a function.

Parent:

```jsx
function App() {
  const [count, setCount] = useState(0);

  function increaseCount() {
    setCount(prev => prev + 1);
  }

  return (
    <Child onIncrease={increaseCount} />
  );
}
```

Child:

```jsx
function Child({ onIncrease }) {
  return (
    <button onClick={onIncrease}>
      Increase
    </button>
  );
}
```

The flow is:

```text
Parent owns state
       ↓
Parent passes state
       ↓
Parent passes handler
       ↓
Child triggers handler
       ↓
Parent updates state
       ↓
Parent re-renders
       ↓
New state flows down
```

This is one of the most important React patterns.

* * *

# 🧩 Simple Example

Let's build a simple counter.

```jsx
import { useState } from "react";

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

  return (
    <div>
      <CounterDisplay count={count} />

      <CounterButtons
        onIncrease={() =>
          setCount(prev => prev + 1)
        }
      />
    </div>
  );
}

function CounterDisplay({ count }) {
  return <h1>{count}</h1>;
}

function CounterButtons({ onIncrease }) {
  return (
    <button onClick={onIncrease}>
      Increase
    </button>
  );
}

export default App;
```

Notice:

### Parent owns state

```jsx
const [count, setCount] = useState(0);
```

### Display receives the value

```jsx
<CounterDisplay count={count} />
```

### Button receives the function

```jsx
<CounterButtons onIncrease={...} />
```

The state stays in the parent.

* * *

# 🔥 Why Not Keep State Inside the Child?

We could do:

```jsx
function CounterButtons() {
  const [count, setCount] = useState(0);
}
```

But now `CounterDisplay` doesn't know about that state.

If multiple components need the same information, keeping the state inside one child makes sharing difficult.

So we move it upward.

* * *

# 📦 Example: Temperature Converter

This is a classic example of lifting state.

Suppose we want:

```text
Celsius: [ 25 ]

Fahrenheit: 77
```

Both values represent the same temperature.

We don't need two independent sources of truth.

We can store Celsius in the parent:

```jsx
import { useState } from "react";

function App() {
  const [temperature, setTemperature] = useState("");

  const fahrenheit =
    temperature === ""
      ? ""
      : temperature * 9 / 5 + 32;

  return (
    <div>
      <TemperatureInput
        value={temperature}
        onChange={setTemperature}
      />

      <h2>
        Fahrenheit: {fahrenheit}
      </h2>
    </div>
  );
}
```

The state is shared through the parent.

* * *

# 🧮 Derived Data

Notice something important:

We didn't create:

```jsx
const [fahrenheit, setFahrenheit] = useState("");
```

Instead:

```jsx
const fahrenheit =
  temperature === ""
    ? ""
    : temperature * 9 / 5 + 32;
```

Why?

Because Fahrenheit is **derived from Celsius**.

We already have the source data.

There's no need to create another state variable for something we can calculate.

This is an important state-management principle:

> **Don't store data in state if it can be calculated from existing state or props.**

* * *

# 🛒 Real-World Example: Shopping Cart

Imagine an application with:

```text
                App
                 │
        ┌────────┴─────────┐
        ↓                  ↓
   ProductList        CartSummary
```

`ProductList` needs to add products.

`CartSummary` needs to display the cart.

The cart state can live in `App`.

```jsx
function App() {
  const [cart, setCart] = useState([]);

  function addToCart(product) {
    setCart(prev => [...prev, product]);
  }

  return (
    <>
      <ProductList
        onAddToCart={addToCart}
      />

      <CartSummary
        cart={cart}
      />
    </>
  );
}
```

Now:

```text
                App
                 │
           cart state
           /         \
          ↓           ↓
 ProductList      CartSummary
     │                 │
     │                 │
 addToCart         cart data
```

This is exactly how component communication starts to work in larger applications.

* * *

# 🔄 Child-to-Parent Communication

Technically, React's data flow is still one-way.

The child isn't directly sending state upward.

Instead:

```text
Parent
  ↓
passes function
  ↓
Child
  ↓
calls function
  ↓
Parent updates state
```

This can feel like "child-to-parent communication," but the actual mechanism is:

> **Parent passes a callback to the child.**

* * *

# 📞 Callback Props

A function passed through props is often called a **callback prop**.

Parent:

```jsx
function handleDelete(id) {
  console.log("Delete:", id);
}

<Task
  onDelete={handleDelete}
/>
```

Child:

```jsx
function Task({ onDelete }) {
  return (
    <button onClick={() => onDelete(10)}>
      Delete
    </button>
  );
}
```

The child invokes:

```jsx
onDelete(10);
```

The parent's function runs.

* * *

# 🧠 Passing Arguments Through Callbacks

This is extremely common.

Parent:

```jsx
function handleSelect(id) {
  console.log(id);
}
```

Pass:

```jsx
<UserList onSelect={handleSelect} />
```

Child:

```jsx
function UserList({ onSelect }) {
  return (
    <button onClick={() => onSelect(101)}>
      Select User
    </button>
  );
}
```

The child doesn't need to know what the parent will do.

It simply calls the callback.

* * *

# 🧩 Lifting State in Forms

Yesterday we learned controlled forms.

Now let's combine that with lifting state.

Suppose we have:

```text
App
 │
 ├── SearchInput
 │
 └── SearchResults
```

Both need the search query.

Instead of storing the query separately:

```text
SearchInput
  ↓
query state

SearchResults
  ↓
query state
```

we lift it:

```text
             App
              │
         query state
          /       \
         ↓         ↓
 SearchInput   SearchResults
```

Parent:

```jsx
function App() {
  const [query, setQuery] = useState("");

  return (
    <>
      <SearchInput
        query={query}
        onQueryChange={setQuery}
      />

      <SearchResults
        query={query}
      />
    </>
  );
}
```

Now both components always use the same query.

* * *

# 🔎 Search Example

```jsx
function SearchInput({ query, onQueryChange }) {
  return (
    <input
      value={query}
      onChange={event =>
        onQueryChange(event.target.value)
      }
      placeholder="Search..."
    />
  );
}
```

Results:

```jsx
function SearchResults({ query }) {
  return (
    <p>
      Searching for: {query}
    </p>
  );
}
```

The parent owns the state.

* * *

# 🧠 Why This Pattern Is Powerful

Imagine a real application:

```text
Search Bar
    ↓
Search State
    ↓
┌───────────────────────────────┐
│                               │
↓                               ↓
Search Results              Result Count
```

All components can stay synchronized because they depend on the same state.

Without lifting state, you might end up with:

```text
Search Bar → query A

Results → query B

Count → query C
```

Now synchronization becomes difficult.

* * *

# 🔄 Lifting State + Conditional Rendering

We can combine today's concept with Day 65.

```jsx
function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <>
      <Navbar
        isLoggedIn={isLoggedIn}
        onLogout={() => setIsLoggedIn(false)}
      />

      {isLoggedIn ? (
        <Dashboard />
      ) : (
        <Login
          onLogin={() => setIsLoggedIn(true)}
        />
      )}
    </>
  );
}
```

The parent owns authentication state.

Children receive the data/functions they need.

* * *

# 🧩 Lifting State + Lists

We can also combine this with Day 66.

```jsx
function App() {
  const [selectedId, setSelectedId] = useState(null);

  const users = [
    { id: 1, name: "Saurabh" },
    { id: 2, name: "Rahul" },
    { id: 3, name: "Aman" }
  ];

  return (
    <UserList
      users={users}
      selectedId={selectedId}
      onSelect={setSelectedId}
    />
  );
}
```

Inside:

```jsx
function UserList({
  users,
  selectedId,
  onSelect
}) {
  return (
    <div>
      {users.map(user => (
        <button
          key={user.id}
          onClick={() => onSelect(user.id)}
        >
          {user.name}
        </button>
      ))}

      {selectedId && (
        <p>
          Selected User ID: {selectedId}
        </p>
      )}
    </div>
  );
}
```

Now we're combining:

```text
State
+
Events
+
Props
+
Lists
+
Conditional Rendering
```

* * *

# 🚨 When Should You Lift State?

A good rule is:

> **Lift state when multiple components need access to the same changing data.**

For example:

```text
Component A needs state
Component B needs state
        ↓
Find common parent
        ↓
Move state there
        ↓
Pass value + handlers through props
```

* * *

# ⚠️ Don't Lift State Too Far

There is also an opposite mistake.

You don't need to move every piece of state to the highest possible component.

Suppose:

```jsx
function PasswordInput() {
  const [showPassword, setShowPassword] = useState(false);
}
```

If only `PasswordInput` needs this state, keep it there.

Don't move it all the way to `App` unnecessarily.

Good state placement is:

> **Keep state as close as possible to where it's needed, but lift it when siblings need to share it.**

* * *

# 🧠 State Placement Rule

Think about it like this:

```text
Only one component needs it?
        ↓
Keep state there.

Multiple siblings need it?
        ↓
Lift state to their common parent.

Many distant components need it?
        ↓
You may eventually need a broader state-management solution.
```

We'll encounter those patterns later.

* * *

# 🏗️ Example: Accordion

Imagine an FAQ:

```text
What is React?
      ↓
Answer

What is State?
      ↓
Answer

What are Props?
      ↓
Answer
```

If we want only one item open at a time, the parent can own:

```jsx
const [activeIndex, setActiveIndex] = useState(null);
```

Then each FAQ item receives:

```jsx
isActive
onClick
```

This allows the parent to control which child is active.

* * *

# 🧠 Controlled Components Beyond Forms

The concept we've learned today is broader than forms.

A component can be "controlled" by its parent whenever the parent owns the relevant state and passes the current value plus callbacks.

For example:

```jsx
<Tabs
  activeTab={activeTab}
  onTabChange={setActiveTab}
/>
```

or:

```jsx
<Modal
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
/>
```

or:

```jsx
<Accordion
  activeIndex={activeIndex}
  onChange={setActiveIndex}
/>
```

The same pattern keeps appearing.

* * *

# 🏆 Best Practices

### 1\. Find the common parent

When two components need the same state, identify their closest common parent.

* * *

### 2\. Keep one source of truth

Don't maintain duplicate copies of the same state unnecessarily.

* * *

### 3\. Pass data down through props

```jsx
<Component value={value} />
```

* * *

### 4\. Pass callbacks down for updates

```jsx
<Component onChange={handleChange} />
```

* * *

### 5\. Don't modify parent state directly

The child should call the callback.

* * *

### 6\. Don't lift state unnecessarily

If only one component needs it, keep it local.

* * *

### 7\. Avoid duplicate derived state

If something can be calculated from existing state, calculate it instead of storing another state variable.

* * *

# 🔥 Complete Example: Shared Counter

Let's put everything together.

```jsx
import { useState } from "react";

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

  function increase() {
    setCount(prev => prev + 1);
  }

  function decrease() {
    setCount(prev => prev - 1);
  }

  return (
    <div>
      <CounterDisplay count={count} />

      <CounterControls
        onIncrease={increase}
        onDecrease={decrease}
      />
    </div>
  );
}

function CounterDisplay({ count }) {
  return (
    <h1>
      Count: {count}
    </h1>
  );
}

function CounterControls({
  onIncrease,
  onDecrease
}) {
  return (
    <div>
      <button onClick={onIncrease}>
        +
      </button>

      <button onClick={onDecrease}>
        -
      </button>
    </div>
  );
}

export default App;
```

Notice how clean the responsibilities are.

### `App`

Owns the state.

### `CounterDisplay`

Displays the value.

### `CounterControls`

Triggers updates.

```text
             App
              │
          count state
           /       \
          ↓         ↓
      Display    Controls
        ↑          │
        │          │
        └──────────┘
          callbacks
```

This is excellent component design.

* * *

# 💡 My Biggest Takeaway

Today's biggest takeaway is:

> **When multiple components need the same state, don't create duplicate state. Lift it to their closest common parent.**

The pattern is:

```text
             Parent
                │
        ┌───────┴────────┐
        ↓                ↓
    Child A           Child B
        ↑                ↑
        └── callbacks ───┘
                │
          Parent State
```

And the fundamental React data flow remains:

```text
State
 ↓
Props
 ↓
Child
 ↓
Callback
 ↓
Parent State Update
 ↓
Re-render
 ↓
Updated Props
```

Once you understand this, component communication becomes much easier to reason about.
