State & Client Interactivity
⏱ 15 min read read
useState --- Client Component State:
State lives in Client Components ('use client'). Every state change
triggers a re-render of that component.
'use client';
import { useState } from 'react';
// const [value, setter] = useState(initialValue)
const [count, setCount] = useState(0);
const [name, setName] = useState('');
const [isOpen, setIsOpen] = useState(false);
const [students, setStudents] = useState<Student[]>([]);
Controlled Inputs:
const [email, setEmail] = useState('');
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter email"
/>
Updating Arrays and Objects in State:
// NEVER mutate state directly --- always create new arrays/objects
// Add item
setStudents(prev => [...prev, newStudent]);
// Remove item
setStudents(prev => prev.filter(s => s.id !== id));
// Update item
setStudents(prev => prev.map(s => s.id === id ? { ...s, grade } :
s));
// Update object field
setForm(prev => ({ ...prev, email: 'new@email.com' }));
useReducer --- For Complex State:
type Action = { type: 'ADD'; payload: Student }
| { type: 'REMOVE'; payload: number }
| { type: 'RESET' };
function reducer(state: Student[], action: Action): Student[] {
switch (action.type) {
case 'ADD': return [...state, action.payload];
case 'REMOVE': return state.filter(s => s.id !== action.payload);
case 'RESET': return [];
}
}
const [students, dispatch] = useReducer(reducer, []);
dispatch({ type: 'ADD', payload: newStudent });
State lives in Client Components ('use client'). Every state change
triggers a re-render of that component.
'use client';
import { useState } from 'react';
// const [value, setter] = useState(initialValue)
const [count, setCount] = useState(0);
const [name, setName] = useState('');
const [isOpen, setIsOpen] = useState(false);
const [students, setStudents] = useState<Student[]>([]);
Controlled Inputs:
const [email, setEmail] = useState('');
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter email"
/>
Updating Arrays and Objects in State:
// NEVER mutate state directly --- always create new arrays/objects
// Add item
setStudents(prev => [...prev, newStudent]);
// Remove item
setStudents(prev => prev.filter(s => s.id !== id));
// Update item
setStudents(prev => prev.map(s => s.id === id ? { ...s, grade } :
s));
// Update object field
setForm(prev => ({ ...prev, email: 'new@email.com' }));
useReducer --- For Complex State:
type Action = { type: 'ADD'; payload: Student }
| { type: 'REMOVE'; payload: number }
| { type: 'RESET' };
function reducer(state: Student[], action: Action): Student[] {
switch (action.type) {
case 'ADD': return [...state, action.payload];
case 'REMOVE': return state.filter(s => s.id !== action.payload);
case 'RESET': return [];
}
}
const [students, dispatch] = useReducer(reducer, []);
dispatch({ type: 'ADD', payload: newStudent });
Log in to track your progress and earn badges as you complete lessons.
Log In to Track Progress