What is «state lifting» in React?

👨‍💻 Frontend Developer 🟠 May come up 🎚️ Medium
#React

Brief Answer

State lifting is a technique in React where state is moved from child components to their common parent. This allows multiple components to share and manage the same state. State lifting is necessary when multiple components need to display the same data or when child components need to interact with each other.

Main reasons for state lifting:

  • Data sharing — multiple components need the same data
  • Component communication — child components need to interact
  • Single source of truth — centralized state management

Full Answer

State lifting is one of the fundamental concepts in React that helps manage application state at the parent component level. This technique allows for more predictable and maintainable code.

When State Lifting is Needed

State lifting is necessary in the following cases:

1. Data Sharing

When multiple components need the same data:

// Parent component with lifted state
function App() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <CounterDisplay count={count} />
      <CounterButton onClick={() => setCount(count + 1)} />
    </div>
  );
}

2. Component Communication

When child components need to interact:

// Parent manages state of both child components
function Form() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  
  return (
    <form>
      <NameInput value={name} onChange={setName} />
      <EmailInput value={email} onChange={setEmail} />
    </form>
  );
}

Practical Examples

Counter Example

// Without state lifting - components are not synchronized
function BadExample() {
  return (
    <div>
      <Counter />
      <Counter />
    </div>
  );
}
 
// With state lifting - synchronized state
function GoodExample() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <Counter count={count} setCount={setCount} />
      <Counter count={count} setCount={setCount} />
    </div>
  );
}

Form Example

function UserForm() {
  const [userData, setUserData] = useState({
    name: '',
    email: '',
    age: ''
  });
  
  // All form fields are managed from one state
}

Common Mistakes

1. Unnecessary State Lifting

// ❌ State lifting when not needed
function Parent() {
  const [child1State, setChild1State] = useState('');
  const [child2State, setChild2State] = useState('');
  
  return (
    <div>
      <Child1 state={child1State} setState={setChild1State} />
      <Child2 state={child2State} setState={setChild2State} />
    </div>
  );
}
 
// ✅ State remains in child components
function Parent() {
  return (
    <div>
      <Child1 />
      <Child2 />
    </div>
  );
}

2. Lifting All State

// ❌ Lifting all child component state
function Parent() {
  const [childState, setChildState] = useState({
    localData: '',
    localPreference: '',
    localUIState: false
  });
  
  return <Child state={childState} setState={setChildState} />;
}
 
// ✅ Only necessary state is lifted
function Parent() {
  const [sharedData, setSharedData] = useState('');
  
  return <Child sharedData={sharedData} setSharedData={setSharedData} />;
}

Best Practices

  1. Lift only what’s necessary — don’t move all state up
  2. Create clean interfaces — use clear prop names
  3. Avoid deep nesting — for deep hierarchies, use Context
  4. Separate state by responsibility — each state piece should have one reason to change
  5. Use destructuring — for convenient work with lifted state

Compatibility

State lifting is a standard React practice that works in all versions of the library.

Key Benefits of State Lifting

  1. Single source of truth — one state manages multiple components
  2. Data synchronization — all components display current data
  3. Simplified debugging — state is in one place
  4. Predictability — application behavior becomes more predictable
  5. Easy testing — easier to test components with lifted state

State lifting is an important technique for creating predictable and maintainable React applications, allowing efficient management of shared state among multiple components.


Knowledge Check Task

Task

What’s the difference between these two approaches and which is preferable?

// Approach 1: State in child components
function Parent() {
  return (
    <div>
      <Input1 />
      <Input2 />
      <SubmitButton />
    </div>
  );
}
 
// Approach 2: State lifting
function Parent() {
  const [value1, setValue1] = useState('');
  const [value2, setValue2] = useState('');
  
  return (
    <div>
      <Input1 value={value1} onChange={setValue1} />
      <Input2 value={value2} onChange={setValue2} />
      <SubmitButton 
        onSubmit={() => console.log({ value1, value2 })} 
      />
    </div>
  );
}
View answer

Answer: Approach 2 (with state lifting) is preferable.

Explanation:

Approach 1 (without lifting):

  • Each Input component manages its state independently
  • SubmitButton has no access to values from Input
  • Impossible to get and submit form data as a whole
  • Components cannot interact with each other
  • State is fragmented, making management difficult

Approach 2 (with state lifting):

  • Parent manages all form state
  • SubmitButton has access to all values
  • Can easily get and submit all form data
  • Components are synchronized
  • Single source of truth for form data
  • Simplified validation and data processing

When to use each approach:

  • Approach 1 is suitable for completely independent components
  • Approach 2 is necessary when components need to interact or when parent needs to manage child data

State lifting is especially important when working with forms, filters, sorting, and other scenarios where multiple components need to work with shared data.


Want more articles to prepare for interviews? Subscribe to EasyAdvice, bookmark the site and improve yourself every day 💪