Skip to content

Instantly share code, notes, and snippets.

@npverni
Last active January 16, 2023 23:24
Show Gist options
  • Save npverni/30c5930209d03ddcdd4ee1ff40263f8f to your computer and use it in GitHub Desktop.
Save npverni/30c5930209d03ddcdd4ee1ff40263f8f to your computer and use it in GitHub Desktop.
useConnector: A custom hook that enables a redux-like setup with action creators using useReducer under the hood
export const inc = () =>
dispatch => dispatch({ type: 'inc' });
export const dec = () =>
dispatch => dispatch({ type: 'dec' });
import React from 'react';
import useConnector from './useConnector';
import reducer from './reducer';
import * as unboundActions from './actions';
const App = () => {
const initialState = { count: 0 };
const [state, actions] = useConnector(initialState, reducer, unboundActions);
return (
<div>
Counter: {state.count}
<button onClick={actions.inc}>+</button>
<button onClick={actions.dec}>-</button>
</div>
);
}
export default App;
const reducer = (state, action) => {
switch (action.type) {
case 'inc':
return { ...state, count: state.count + 1};
case 'dec':
return { count: state.count - 1};
default:
throw new Error();
}
}
export default reducer;
import { useReducer } from 'react';
const bindActionsToDispatchAndState = (unboundActions, dispatch, state) =>
Object.keys(unboundActions).map(key =>
[key, (...args) => unboundActions[key](...args)(dispatch, state)],
).reduce(
(acc, cur) => ({ ...acc, [cur[0]]: cur[1] }),
{},
);
const useConnector = (
initialState,
reducer,
unboundActions,
) => {
const [state, dispatch] = useReducer(reducer, initialState);
const actions = bindActionsToDispatchAndState(unboundActions, dispatch, state);
return [state, actions];
};
export default useConnector;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment