- React
- State Mechanics, Batching, and Lifecycle Transitions
- Derived State vs Redundant State Patterns
Derived State vs Redundant State Patterns
If a value can be computed from existing props or state, never mirror it in state. Storing derived values in state creates duplicate sources of truth that easily become desynchronized and trigger unnecessary extra re-renders.
Key Learning Objectives
Recognize the redundant state anti-pattern and why copying props to state causes desync bugs.
Compute derived values during render instead of synchronizing them in useEffect.
Use useMemo responsibly only when derived calculations are computationally expensive.
Structure state around minimal, normalized data representations.
The Interview Problem & Context
Refactor the following component to eliminate redundant state synchronization. What are the key principles for determining whether a value should live in state?
1// ❌ ANTI-PATTERN: Copying props/state into redundant state via useEffect2function BadUserList({ users, filterText }: { users: User[]; filterText: string }) {3 const [filteredUsers, setFilteredUsers] = useState<User[]>([]);45 // Buggy & slow: triggers an extra, redundant re-render every time filterText changes!6 useEffect(() => {7 setFilteredUsers(users.filter(u => u.name.toLowerCase().includes(filterText.toLowerCase())));8 }, [users, filterText]);910 return <ul>{filteredUsers.map(u => <li key={u.id}>{u.name}</li>)}</ul>;11}1213// ✅ BEST PRACTICE: Derived state calculated directly during render14function GoodUserList({ users, filterText }: { users: User[]; filterText: string }) {15 // Pure calculation: runs during render with zero extra re-renders or useEffect latency16 const filteredUsers = users.filter(u =>17 u.name.toLowerCase().includes(filterText.toLowerCase())18 );1920 return <ul>{filteredUsers.map(u => <li key={u.id}>{u.name}</li>)}</ul>;21}
Deep Architectural Explanation
The Golden Rule of React State Structure
Don't put in state what you can compute from props or existing state.
Why Redundant State Causes Bugs
When you duplicate data into state via useEffect:
- Double Rendering: The component renders with old state, then
useEffectruns, updates state, and forces a second re-render. - Desynchronization Glitches: Between render 1 and render 2, the UI displays outdated or mismatched data.
- Boilerplate & Complexity: You now have to maintain dependency arrays and ensure all update pathways update both variables.
When to Use useMemo for Derived Values
Calculate derived values directly in the component body:
const filteredList = items.filter(item => item.active);Only wrap in useMemo if:
- The calculation involves thousands of items or expensive algorithms (e.g.
> 1msexecution time). - The derived object/array reference is passed to a memoized child component (
React.memo) that requires referential stability.
Common Interview Traps & Pitfalls
Using useEffect to sync filtered lists, search results, or selected item IDs into state.
Copying props into initial state: const [name, setName] = useState(props.initialName) and expecting it to update when props change.
Wrapping every simple derived expression in useMemo, adding more overhead than the calculation itself.
Senior Interviewer Follow-Up Probes
How do you reset component state when a prop changes without using useEffect?
What is the difference between initial state and synced state in React?
How does the React team's "You Might Not Need an Effect" documentation advise handling derived state?
Frequently Asked Interview Questions
Why is using useEffect to sync props into state an anti-pattern?
It causes a double render pass (first with outdated state, then with updated state), introduces brief visual UI flickers, and creates synchronization bugs.
When should derived state be memoized with useMemo?
Only when the calculation is computationally expensive (sorting or filtering large datasets) or when the resulting array/object is passed as a prop to a memoized child component.
How do you reset state when a prop (like userId) changes?
By passing a unique key prop to the component: <UserProfile key={userId} userId={userId} />. React automatically unmounts and remounts a fresh instance with clean state.
What does "single source of truth" mean in React state design?
It means each piece of data is stored in exactly one place. All other views, counts, and filters are calculated from that single source, eliminating data discrepancies.
