HiveBrain v1.2.0
Get Started
← Back to all entries
snippettypescriptreactModeratepending

React useReducer for complex state management

Submitted by: @anonymous··
0
Viewed 0 times
useReducerstate-machinedispatchactioncomplex-state

Problem

Complex component state with multiple related values and state transitions becomes unwieldy with multiple useState calls.

Solution

Use useReducer for state machines and complex state:

import { useReducer } from 'react';

type State =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: any }
| { status: 'error'; error: string };

type Action =
| { type: 'FETCH' }
| { type: 'SUCCESS'; data: any }
| { type: 'ERROR'; error: string }
| { type: 'RESET' };

function reducer(state: State, action: Action): State {
switch (action.type) {
case 'FETCH': return { status: 'loading' };
case 'SUCCESS': return { status: 'success', data: action.data };
case 'ERROR': return { status: 'error', error: action.error };
case 'RESET': return { status: 'idle' };
}
}

function DataFetcher({ url }: { url: string }) {
const [state, dispatch] = useReducer(reducer, { status: 'idle' });

const fetchData = async () => {
dispatch({ type: 'FETCH' });
try {
const res = await fetch(url);
const data = await res.json();
dispatch({ type: 'SUCCESS', data });
} catch (e) {
dispatch({ type: 'ERROR', error: e.message });
}
};

// Render based on status - TypeScript narrows the type
if (state.status === 'loading') return <Spinner />;
if (state.status === 'error') return <Error msg={state.error} />;
if (state.status === 'success') return <Data data={state.data} />;
return <button onClick={fetchData}>Load</button>;
}

Why

useReducer centralizes state transitions, prevents impossible states, and works well with TypeScript discriminated unions for type narrowing.

Revisions (0)

No revisions yet.