Skip to content

Instantly share code, notes, and snippets.

@subhog
Created January 20, 2020 21:04
Show Gist options
  • Save subhog/6e00e88a7d40e8e7a8223b8e77228faf to your computer and use it in GitHub Desktop.
Save subhog/6e00e88a7d40e8e7a8223b8e77228faf to your computer and use it in GitHub Desktop.
The simplest useImmer hook
import { useReducer } from "react";
import produce from "immer";
export default (initialState) => (
/*
First, we need to apply the `useReducer` hook.
React reducer signature is `(state, action)`, where `state` is the current state
and `action` is the argument provided to the `set` method.
In our case, `action` is just the `producer` method we'll pass to immer.
The reducer should return the new state, which we get via immer's `produce` method.
const [state, dispatch] = useReducer((state, producer) => produce(state, producer), initialState);
Notice that the reducer method is trivial here, so this line can be simplified to:
const [state, dispatch] = useReducer(produce, initialState);
Now, we want to return an `useState`-like pair where the method accepts a producer
and dispatches it as a new action:
return [state, (producer) => dispatch(producer)];
Notice that this again is trivially simplified to:
return [state, dispatch];
Which is exactly what we got from the previous line.
Hence, we arrived at this somewhat cryptic one liner.
*/
useReducer(produce, initialState)
);
/*
Usage example:
const [state, setState] = useImmer({});
...
setState(state => {
state.changed = true;
});
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment