useReducer: An Editor with Undo
Mission
Build complex state logic with a reducer that tracks history (undo/redo), keeping all of it out of the UI.
Tasks
- 1
Model the state as
{ past, present, future }. - 2
Handle
SET_TEXT: push the currentpresentintopast, set the newpresent, and clearfuture. - 3
Handle
UNDO: movepresentto the front offutureand take the last item ofpastas the newpresent. - 4
Handle
REDO: the reverse ofUNDO. - 5
Return the same state when there is nothing to undo or redo.
- 6
Never mutate: build new arrays and objects every time.
import React, { useReducer } from 'react'; // 1. Define your initial state here const initialState = { past: [], present: '', future: [] }; // 2. Implement the reducer function function reducer(state, action) { const { past, present, future } = state; switch (action.type) { case 'SET_TEXT': // Tip: save present into past before changing it return state; case 'UNDO': // Tip: the new present comes from past return state; case 'REDO': return state; default: return state; } } export default function EditorWithMemory() { const [state, dispatch] = useReducer(reducer, initialState); return ( <div style={{ padding: '20px', fontFamily: 'sans-serif', textAlign: 'center' }}> <h1>Editor with History</h1> <textarea value={state.present} onChange={(e) => dispatch({ type: 'SET_TEXT', payload: e.target.value })} rows="5" style={{ width: '100%', padding: '10px', fontSize: '1.2rem', boxSizing: 'border-box' }} /> <div style={{ marginTop: '20px', display: 'flex', gap: '10px', justifyContent: 'center' }}> <button onClick={() => dispatch({ type: 'UNDO' })} disabled={state.past.length === 0} > Undo </button> <button onClick={() => dispatch({ type: 'REDO' })} disabled={state.future.length === 0} > Redo </button> </div> <div style={{ marginTop: '20px', color: '#888', fontSize: '0.9rem' }}> <p>Changes in history: {state.past.length}</p> <p>Changes to redo: {state.future.length}</p> </div> </div> ); }
Requirements
0/6SET_TEXT saves the previous value in `past` (not run yet)
UNDO restores the last past value and queues the present in `future` (not run yet)
REDO brings back the undone value (not run yet)
A new change after UNDO clears `future` (not run yet)
UNDO and REDO do nothing when there is no history (not run yet)
The reducer never mutates (no push, pop, splice...) (not run yet)
AI mentor
Reviews only the files you changed, plus the checks you missed.
Run the checks first. They are free and instant.