Reducer pattern

리듀서 패턴

Collect state transitions in actions and a pure reducer function.

···
html
<div class="scene"><div class="formula"><span id="action">dispatch add</span><span>→</span><span>reducer</span><span>→</span><b id="count">0 tasks</b></div><div class="tasklist"><div class="task" id="taskA">Task A <i></i></div><div class="task" id="taskB">Task B <i></i></div></div><div class="label" id="rule">state + action → next state</div></div>
css
.scene{width:min(94vw,800px);height:min(86vh,320px);position:relative;overflow:hidden;display:flex;flex-direction:column;justify-content:space-between;border:1px solid var(--line);border-radius:14px;background:var(--surface);padding:clamp(9px,2.4vmin,20px);font:500 clamp(15px,4vmin,18px)/1.3 var(--font-sans,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif)}.scene b,.scene strong{font-weight:700}.label{color:var(--muted)}.code{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.pill{border:1px solid var(--line);border-radius:8px;padding:.4em .65em;background:var(--bg)}.active{border-color:var(--accent)!important;color:var(--accent)!important;background:color-mix(in srgb,var(--accent) 10%,var(--surface))!important}.formula{display:flex;justify-content:space-between;align-items:center;gap:3px;font:700 clamp(12px,3vmin,15px) ui-monospace,monospace}.formula b{color:var(--accent)}.tasklist{flex:1;min-height:55px;display:flex;gap:8px;align-items:center}.task{flex:1;min-height:42px;border:1px solid var(--line);border-radius:7px;display:flex;align-items:center;justify-content:space-between;padding:.3em .5em;opacity:.25;transition:opacity .3s}.task.visible{opacity:1}.task i{width:12px;height:12px;border:1px solid var(--accent);border-radius:3px}.task.done i{background:var(--accent)}.task.done{text-decoration:line-through;color:var(--muted)}.label{text-align:center;font-size:clamp(12px,3vmin,15px)}
js
const actions=["add A","add B","complete A","reset"];let step=0;function tick(){const action=actions[step];document.getElementById("action").textContent="dispatch "+action;document.getElementById("count").textContent=["1 task","2 tasks","2 tasks","0 tasks"][step];document.getElementById("taskA").classList.toggle("visible",step<3);document.getElementById("taskB").classList.toggle("visible",step===1||step===2);document.getElementById("taskA").classList.toggle("done",step===2);document.getElementById("rule").textContent=step===2?"complete returns a new state":"state + action → next state";step=(step+1)%4}tick();setInterval(tick,1000)

useReducer passes current state and an action to a reducer, then renders from the returned next state. Keeping related transition rules in one function makes multiple event paths easier to inspect.

The demo sends add, complete, and reset actions through a task state. A reducer should return new state without mutating the previous one; handle asynchronous work in an event handler or effect.

When to use

Use it when many event types change one state and its transition rules become hard to follow.

Open as page ↗