Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
use-dispatch-action
Advanced tools
Typed utilities for improving the experience with `useReducer`.
Typed utilities for improving the experience with useReducer
.
When using useReducer
use-dispatch-action
is a collection of utilities to improve the experience when using the useReducer
hook.
Install
yarn add use-dispatch-action
Or
npm install use-dispatch-action
import * as React from 'react';
import { useDispatchAction } from 'use-dispatch-action';
type Actions =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'addValue'; payload: number };
type State = { counter: number };
const reducer = (state: State, action: Actions): State => {
switch (action.type) {
case 'increment':
return { ...state, counter: state.counter + 1 };
case 'decrement':
return { ...state, counter: state.counter - 1 };
case 'addValue':
return { ...state, counter: state.counter + action.payload };
default:
return state;
}
};
const Component = () => {
const [state, dispatch] = React.useReducer(reducer, { counter: 0 });
const increment = useDispatchAction(dispatch, 'increment');
const decrement = useDispatchAction(dispatch, 'decrement');
const addValue = useDispatchAction(dispatch, 'addValue');
return (
<div>
<div title="counter">{state.counter}</div>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={() => addValue(2)}>Add Two</button>
</div>
);
};
Action
A utilty type for defining actions
type Action<TActionType extends string, TPayload = never> = {
type: TActionType;
payload?: TPayload;
};
type Actions = Action<'incrementOne'> | Action<'increment', number>;
useDispatchAction
Creates type safe dispatch functions for the specified action
useDispatchAction<TAction>(
dispatch: React.Dispatch<TAction>,
action: string
) : DispatchAction<TActionPayload>
dispatch: React.Dispatch<TAction>
- A dispatch method retured from React.useReducer
action: string
- The type of the actionDispatchAction<TActionPayload>
- Function to dispatch action// For actions without a payload
() => void;
// For actions with a payload
(payload: TPayload) => void;
const Component = () => {
const [state, dispatch] = React.useReducer(reducer, { counter: 0 });
const increment = useDispatchAction(dispatch, 'increment');
const decrement = useDispatchAction(dispatch, 'decrement');
const addValue = useDispatchAction(dispatch, 'addValue');
return (
<div>
<div title="counter">{state.counter}</div>
<button onClick={() => increment()}>Increment</button>
<button onClick={() => decrement()}>Decrement</button>
<button onClick={() => addValue(2)}>Add Two</button>
</div>
);
};
useDispatchReducer
Creates a reducer with a type safe dispatch method
useDispatchReducer<TState, TAction> (
reducer: React.Reducer<TState, TAction>,
initialState: TState
) : [state: TState, ActionDispatcher<TAction>]
TState
and TAction
can be infered by providing the type of a reducer.
useDispatchReducer<TReducer>(
reducer: TReducer,
initialState: TState
) : [state: TState, ActionDispatcher<TAction>]
reducer: React.Reducer<TState, TAction>
- The reducerinitialState: TState
- State to initialize the reducer with. A note, useDispatchReducer
does not implement lazy loading the stateA tuple with:
state: TState
- State of the reducerActionDispatcher<TAction>
- Function to dispatch actions in the form of tuples
// For actions without a payload
([type: string]) => void;
// For actions with a payload
([type: string, payload: TPayload]) => void;
With type inference
const Component = () => {
const [state, dispatch] = useDispatchReducer(reducer, { counter: 0 });
const increment = () => dispatch(['increment']);
const decrement = () => dispatch(['decrement']);
const addValue = (number: number) => dispatch(['addValue', number]);
return (
<div>
<div title="counter">{state.counter}</div>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={() => addValue(2)}>Add Two</button>
</div>
);
};
With known State and Action types
const Component = () => {
const [state, dispatch] = useDispatchReducer<State, Action>(reducer, {
counter: 0,
});
const increment = () => dispatch(['increment']);
const decrement = () => dispatch(['decrement']);
const addValue = (number: number) => dispatch(['addValue', number]);
return (
<div>
<div title="counter">{state.counter}</div>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={() => addValue(2)}>Add Two</button>
</div>
);
};
Only know the State type? The Action type can be inferred from the reducer as long as the actions are typed.
const Component = () => {
const [state, dispatch] = useDispatchReducer<State>(reducer, { counter: 0 });
const increment = () => dispatch(['increment']);
const decrement = () => dispatch(['decrement']);
const addValue = (number: number) => dispatch(['addValue', number]);
return (
<div>
<div title="counter">{state.counter}</div>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={() => addValue(2)}>Add Two</button>
</div>
);
};
A context based dispatcher used to prevent prop drilling
export type DispatchContextProps = {
initialState: TState;
reducer: React.Reducer<TState, TAction>;
};
initialState: TState
- state to initialize the reducer withreducer: React.Reducer<TState, TAction>
- The reducerUsing a consumer
const DispatchContext = () => {
return (
<DispatchContextProvider reducer={reducer} initialState={{ counter: 0 }}>
<DispatchContextConsumer>
{({ state, dispatch }: DispatchProps<typeof reducer>) => (
<div>
<div title="counter">{state.counter}</div>
<button onClick={() => dispatch(['increment'])}>Increment</button>
<button onClick={() => dispatch(['decrement'])}>Decrement</button>
<button onClick={() => dispatch(['addValue', 2])}>Add Two</button>
</div>
)}
</DispatchContextConsumer>
</DispatchContextProvider>
);
};
Using useDispatchContext
const Component = () => {
return (
<DispatchContextProvider initialState={{ counter: 0 }} reducer={reducer}>
<Counter />
</DispatchContextProvider>
);
};
const Counter = () => {
const [state, dispatch] = useDispatchContext<typeof reducer>();
return (
<div>
<div title="counter">{state.counter}</div>
<button onClick={() => dispatch(['increment'])}>Increment</button>
<button onClick={() => dispatch(['decrement'])}>Decrement</button>
<button onClick={() => dispatch(['addValue', 2])}>Add Two</button>
</div>
);
};
type Actions =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'addValue'; payload: number };
type State = { counter: number };
const reducer = (state: State, action: Actions): State => {
switch (action.type) {
case 'increment':
return { ...state, counter: state.counter + 1 };
case 'decrement':
return { ...state, counter: state.counter - 1 };
case 'addValue':
return { ...state, counter: state.counter + action.payload };
default:
return state;
}
};
1.0.0
FAQs
Typed utilities for improving the experience with `useReducer`.
The npm package use-dispatch-action receives a total of 3 weekly downloads. As such, use-dispatch-action popularity was classified as not popular.
We found that use-dispatch-action demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.