usehooks icon indicating copy to clipboard operation
usehooks copied to clipboard

useBuildReducer (typescript-typesafe useReducer)

Open phryneas opened this issue 5 years ago • 2 comments

Maybe you're at the point where you accept Typescript-contributions - this can of course be used without typescript, but it really shines with typescript ;)

I've got a prototype of this scetched out here: https://codesandbox.io/s/kx4ml7521o

Essentially, you use it like this:

 const [state, dispatchWithType] = useBuildReducer(
    /* initial state: */ { data: "initial text" }
  )
    // add case/action type with payload definition
    .withCase<"concat", string>("concat", (state, action) => ({
      data: state.data + action.payload
    }))
    // add case/action type without payload
    .withCase("toUpper", state => ({ data: state.data.toUpperCase() }))
    // add case/action type without payload
    .withCase("clear", () => ({ data: "" }))
    .build();

and then you can use it like this:

dispatchWithType(type, payload);

so in this case:

dispatchWithType("concat", "some string");
// or
dispatchWithType("clear");

The nice thing about this is that typescript restricts action types to valid action types - and enforces correct payload types - so it's a typesafe useReducer.

I'm thinking about wrapping the reducers in immer, like redux-starter-kit does, but for now this is only a prototype - I'd like some opinion about this.

phryneas avatar Apr 06 '19 18:04 phryneas

Here's a similar idea with another api - very close to the createSlice api of redux-starter-kit : https://codesandbox.io/s/vyv0zlr78y

I named it useLocalSlice after createSlice.

This one works like this:

 const [state, dispatchAction] = useLocalSlice({
    initialState: { data: "initial text" },
    reducers: {
      concat: (state, action: { payload: string }) => ({
        data: state.data + action.payload
      }),
      toUpper: state => ({
        data: state.data.toUpperCase()
      }),
      clear: () => ({ data: "" })
    }
  });

dispatching of actions is just done via

dispatchAction.concat("concatenate me!");
// or
dispatchAction.clear();

again, this is typesafe - you can only use existing action types, and only correct payload types

phryneas avatar Apr 07 '19 11:04 phryneas

And a day later, the second implemention has immer integration, a test suite and is on npm ;) https://www.npmjs.com/package/use-local-slice

I would be honored if you would choose to promote this ^^

phryneas avatar Apr 07 '19 19:04 phryneas