Skip to content

Instantly share code, notes, and snippets.

@tarex
Forked from fnky/hooks.js
Created May 23, 2020 11:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tarex/ba85a4ae3052df8b1c811371cd3e6d63 to your computer and use it in GitHub Desktop.
Save tarex/ba85a4ae3052df8b1c811371cd3e6d63 to your computer and use it in GitHub Desktop.
React Hooks: useReducer with actions and selectors (Redux-like)
function useSelectors(reducer, mapStateToSelectors) {
const [state] = reducer;
const selectors = useMemo(() => mapStateToSelectors(state), [state]);
return selectors;
}
function useActions(reducer, mapDispatchToActions) {
const [, dispatch] = reducer;
const actions = useMemo(() => mapDispatchToActions(dispatch), [dispatch]);
return actions;
}
const initialState = { count: 0 };
function reducer(state = initialState, action) {
switch(action.type) {
case 'increment':
case 'decrement':
return { count: state.count + action.amount };
}
}
function Example() {
const counterReducer = useReducer(reducer, initialState);
const { increment, decrement } = useActions(counterReducer, (dispatch) => ({
increment: (amount) => dispatch({ type: 'increment', amount || 1 }),
decrement: (amount) => dispatch({ type: 'decrement', amount: -(amount || 1) })
}));
const { getCount, getDividedBy } = useSelectors(counterReducer, (state) => ({
getCount: () => state,
getDividedBy: (amount) => state.count / amount
}));
return (
<div>
<p>Current count is {getCount()} and divided by two: {getDividedBy(2)}</p>
<button onClick={() => increment(1)}>+</button>
<button onClick={() => decrement(1)}>-</button>
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment