Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Reducer With Side Effects
module ReducerWithEffects = {
type actionWrapper('state, 'action) =
| Update('state)
| SideEffect(('action => unit) => unit)
| UpdateWithSideEffect('state, ('action => unit) => unit)
| NoUpdate;
type stateWrapper('state, 'action) = {
state: 'state,
effect: option(('action => unit) => unit),
};
let reducerWrapper = (state, action) => {
switch (action) {
| Update(s) => {state: s, effect: None}
| SideEffect(effect) => {...state, effect: Some(effect)}
| UpdateWithSideEffect(state, effect) => {state, effect: Some(effect)}
| NoUpdate => {...state, effect: None}
};
};
let useReducerWithEffects =
(
parentReducer: ('state, 'action) => actionWrapper('state, 'action),
initialState,
) => {
let (state, mainDispatch) =
React.useReducer(reducerWrapper, {state: initialState, effect: None});
let dispatch: 'action => unit =
action => {
let action = parentReducer(state.state, action);
mainDispatch(action);
};
React.useEffect1(
() => {
switch (state.effect) {
| Some(fn) => fn(dispatch)
| None => ()
};
None;
},
[|state.effect|],
);
(state.state, dispatch);
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment