State আর Updating State lesson বেশিরভাগ component state-এর জন্য useState কভার করেছে। useReducer একটা বিকল্প, একটা সহজ মানের বদলে কয়েকটা distinct, ভালো-define করা action দিয়ে বদলানো state-এর জন্য বেশি মানানসই।
একটা reducer এমন একটা function যা বর্তমান state আর একটা action নেয়, আর নতুন state return করে — এই কোর্সের array .reduce() উদাহরণ যে একই pattern ব্যবহার করে, শুধু component state-এ প্রয়োগ করা।
function counterReducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
case 'reset':
return { count: 0 }
default:
throw new Error(`Unknown action: ${action.type}`)
}
}import { useReducer } from 'react'
function Counter() {
const [state, dispatch] = useReducer(counterReducer, { count: 0 })
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
)
}State পরিবর্তন trigger করার একমাত্র উপায় dispatch — একটা component কখনো সরাসরি state সেট করে না, এটা কী ঘটেছে (action) বর্ণনা করে আর reducer-কে ফলাফল ঠিক করতে দেয়।
| যখন useState ব্যবহার করবেন... | যখন useReducer ব্যবহার করবেন... |
|---|---|
| State একটা একক মান বা কয়েকটা স্বাধীন মান | একই event-এর প্রতিক্রিয়ায় state-এর বেশ কয়েকটা অংশ একসাথে আপডেট হয় |
| আপডেট সহজ — এটাকে ওটা সেট করা | পরের state সত্যিকারভাবে বর্তমান state আর কোন action fire হয়েছে তার উপর নির্ভর করে |
| ভিন্ন আপডেটের মধ্যে কোনো শেয়ার করা logic নেই | একই transition logic component থেকে আলাদা, নিজে থেকেই testable হওয়া দরকার |
কেন এটা test করা সহজ
একটা reducer function React-এর উপর কোনো নির্ভরতা নেই — এটা state আর একটা action নেওয়া, নতুন state return করা একটা সাধারণ function। এটা কিছু render না করেই unit test করা সহজ বানায়।
function formReducer(state, action) {
switch (action.type) {
case 'field-changed':
return { ...state, [action.field]: action.value }
case 'reset':
return { name: '', email: '' }
default:
return state
}
}
function SignupForm() {
const [form, dispatch] = useReducer(formReducer, { name: '', email: '' })
return (
<input
value={form.name}
onChange={(e) => dispatch({ type: 'field-changed', field: 'name', value: e.target.value })}
/>
)
}