Code Example 1: useState basic counter
❓ Что произойдёт при клике на кнопку? Как useState сохраняет значение между рендерами?
function Counter() {
const [count, setCount] = useState(0)
return (
<button onClick={() => setCount(count + 1)}>
Нажато {count} раз
</button>
)
}
Code Example 2: useReducer basic counter
❓ В чём разница между useState и useReducer в этих примерах? Когда лучше использовать useReducer?
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default:
return state
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 })
return (
<>
<span>{state.count}</span>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
)
}
Code Example 3: useState vs useReducer counter comparison
❓ Какой подход проще для счётчика с тремя кнопками? Какой будет предпочтительнее при добавлении новых действий?
useState:
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
)
}
useReducer:
type Action = { type: 'inc' } | { type: 'dec' } | { type: 'reset' }
function reducer(state: number, action: Action): number {
switch (action.type) {
case 'inc': return state + 1
case 'dec': return state - 1
case 'reset': return 0
}
}
function Counter() {
const [count, dispatch] = useReducer(reducer, 0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch({ type: 'inc' })}>+</button>
<button onClick={() => dispatch({ type: 'dec' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
)
}
Code Example 4: Object mutation problem
❓ Почему Version A не работает? Как правильно обновлять объект в state?
Version A:
const [user, setUser] = useState({ name: 'John', age: 25 })
user.name = 'Jane'
setUser(user)
Version B:
setUser({ ...user, name: 'Jane' })
Code Example 5: setState is asynchronous
❓ Что выведет console.log? Почему значение ещё не обновилось?
const [count, setCount] = useState(0)
function handleClick() {
setCount(count + 1)
console.log(count)
}
Code Example 6: Functional updater for multiple updates
❓ Какой результат будет в каждом случае при быстрых кликах? Почему?
Version A:
setCount(count + 1)
setCount(count + 1)
Version B:
setCount(prev => prev + 1)
setCount(prev => prev + 1)
Code Example 7: Lazy initialization
❓ В чём разница между этими двумя вариантами? Какой более производительный?
const [data, setData] = useState(expensiveCalculation())
const [data, setData] = useState(() => expensiveCalculation())