use-typed-reducer
v4.3.0
Published
use-reducer React hook alternative
Downloads
1,966
Readme
use-typed-reducer
A powerful, type-safe React hook alternative to useReducer with built-in support for async actions, middleware, debugging, and global state management.
Features
- 🔷 Full TypeScript support - Complete type safety for state and actions
- ⚡ Async actions - Built-in support for Promise-based reducers
- 🔧 Middleware system - Extensible middleware for side effects and transformations
- 🌍 Global state management - Create global stores with selectors
- 🐛 Development tools - Built-in debugging with performance metrics
- 💾 Storage plugins - localStorage and sessionStorage integration
- 🔄 Legacy compatibility - Drop-in replacement for standard useReducer
Installation
npm install use-typed-reduceryarn add use-typed-reducerpnpm add use-typed-reducerQuick Start
Basic Usage
import useReducer, { ReducerArgs } from 'use-typed-reducer';
interface CounterState {
count: number;
}
const initialState: CounterState = { count: 0 };
function Counter() {
const [state, actions] = useReducer(initialState, (get) => ({
reset: () => initialState,
increment: () => ({ count: state.count + 1 }),
decrement: () => ({ count: state.count - 1 }),
setCount: (value: number) => ({ count: value })
}));
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => actions.increment()}>+</button>
<button onClick={() => actions.decrement()}>-</button>
<button onClick={() => actions.reset()}>Reset</button>
<button onClick={() => actions.setCount(10)}>Set to 10</button>
</div>
);
}Async Actions
const asyncReducer = (get) => ({
fetchUser: async (userId: string) => {
const user = await fetch(`/api/users/${userId}`).then(res => res.json());
return ({ ...get.state(), user, loading: false });
},
// you can omit properties to merge with the previous state
setLoading: (loading: boolean) => ({ loading })
});With Props and State Access
const reducerWithContext = ({ state, props, initialState, previousState }) => ({
updateWithProps: () => (currentState: State) => ({
...currentState,
value: props().multiplier * currentState.value
}),
revertToPrevious: () => () => previousState(),
resetToInitial: () => () => initialState
});Advanced Usage
Global State Management
Create a global store that can be accessed from any component:
import { createGlobalReducer } from 'use-typed-reducer';
interface AppState {
user: User | null;
theme: 'light' | 'dark';
}
const globalStore = createGlobalReducer(
{ user: null, theme: 'light' },
() => ({
setUser: (user: User) => ({ user }),
toggleTheme: () => ({
theme: state.theme === 'light' ? 'dark' : 'light'
})
})
);
// Use in any component
function UserProfile() {
const [state, actions] = globalStore(
state => ({ user: state.user }), // selector
(a, b) => a.user?.id === b.user?.id // custom comparator
);
return (
<div>
{state.user ? (
<p>Welcome, {state.user.name}!</p>
) : (
<button onClick={() => actions.setUser({ id: 1, name: 'John' })}>
Login
</button>
)}
</div>
);
}Middleware and Debugging
import { createLoggerPlugin, createLocalStoragePlugin } from 'use-typed-reducer';
const [state, actions] = useReducer(
initialState,
reducer,
{
debug: true, // Enable performance debugging
postMiddleware: [
createLoggerPlugin('MyComponent'), // Console logging
createLocalStoragePlugin('app-state') // Auto-save to localStorage
]
}
);Custom Middleware
const customMiddleware = (state, previousState, debug) => {
console.log(`Action "${debug.method}" took ${debug.time}ms`);
// Transform state
return {
...state,
lastUpdated: Date.now()
};
};
const [state, actions] = useReducer(initialState, reducer, {
postMiddleware: [customMiddleware]
});Storage Plugins
import {
createLocalStoragePlugin,
createSessionStoragePlugin,
createStoragePlugin
} from 'use-typed-reducer';
// Built-in plugins
const localStorage = createLocalStoragePlugin('my-app-state');
const sessionStorage = createSessionStoragePlugin('temp-state');
// Custom storage plugin
const customStorage = createStoragePlugin(() => ({
set: (key, value) => {
// Custom storage logic
myCustomStorage.save(key, value);
}
}));
const [state, actions] = useReducer(initialState, reducer, {
postMiddleware: [localStorage('user-preferences')]
});API Reference
useReducer(initialState, reducer, options?)
The main hook for local state management.
Parameters:
initialState: State- Initial state objectreducer: ReducerActions<State, Props>- Function returning action creatorsoptions?: Options- Configuration options
Options:
{
props?: Props; // Props passed to reducer
debug?: boolean; // Enable debug mode
postMiddleware?: Array; // Middleware functions
interceptor?: Array; // State interceptors
}Returns: [state, actions, props]
createGlobalReducer(initialState, reducer, options?)
Creates a global store accessible from any component.
Returns: A hook function with additional properties:
dispatchers- Direct access to action dispatchersgetState()- Get current state snapshot
useLegacyReducer(initialState, reducers, props?)
Legacy compatibility mode that mimics standard useReducer behavior.
Utility Hooks
usePrevious<T>(value: T): T- Get the previous valueuseMutable<T>(state: T): RefObject<T>- Create a mutable ref that updates with state
Development
# Install dependencies
pnpm install
# Run tests
pnpm test
# Build the library
pnpm build
# Format code
pnpm formatRequirements
- React >= 16.8.3
- TypeScript >= 4.0 (for TypeScript projects)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT © g4rcez
