question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal implementation of handleActions

See original GitHub issue

Really nice solution for typing Redux! It’s exactly what I’ve been looking for for a while! Thanks! 😄

Feature ~request~ proposal

Use case(s)

One thing I really like from redux-actions is handleActions. For me it’s much cleaner than switch statements.

The problem is it doesn’t play well with rex-tils’s approach, which is much better IMHO.

I created this version of handleActions:

const handleActions = <
  State,
  Types extends string,
  Actions extends ActionsUnion<{ [T in Types]: AnyFunction }>
>(
  handler: {
    [T in Types]: (state: State, action: ActionsOfType<Actions, T>) => State
  },
  initialState: State,
) => (state = initialState, action: Actions): State =>
  handler[action.type] ? handler[action.type](state, action) : state;

Which can be used like this:

interface State {
  foo: boolean,
  bar: number,
}

enum Types {
  FOO = 'FOO',
  BAR = 'BAR',
}

const Actions = {
  foo: () => createAction(Types.FOO),
  bar: (bar: number) => createAction(Types.FOO, bar),
}

const reducer = handleActions<State, Types, Actions>(
  {
    [Types.FOO]: (state) => ({ ...state, foo: !state.foo }),
    [Types.BAR]: (state, { payload }) => ({ ...state, bar: payload, }),
  },
  { foo: true, bar: 0 },
)

Enums are not necessary, it works with constants but requires a few lines more:

...

const FOO = 'FOO'
const BAR = 'BAR'

type Types =
  | typeof FOO
  | typeof BAR

...

Props

  • Works as the switch version, type of action is inferred for each case, but much less boilerplate
  • The handler object expects all the types to be “handled” (i.e. you get a type error if one of the action types is not covered)

Cons

  • handleActions expects 3 type parameters. I tried to find a way to make it work only with State and Actions but I’m not sure is possible. Maybe I’m missing something.

If you think this is worth adding to rex-tils I can create a Pull Request.

Edit handle-actions

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:3
  • Comments:7

github_iconTop GitHub Comments

1reaction
raybooysencommented, Jun 14, 2019

You absolute hero! I’ve been battling with my implementation of Handler because I didn’t know how to express the key in the actions type properly

type Handler<State, ActionType extends string, Actions> = 
  (s: State, a: ActionsOfType<Actions, ActionType>) => State

const barHandler: Handler<State, 'bar', Actions> =
  (s, { payload }) => ({n: s.n + payload})

The use of bar here is what I was missing which made my handlers not pick up the change in action shapes. I really appreciate this, ty

0reactions
gillchristiancommented, Jun 13, 2019

Thanks will give it a try. Checking your code’s TS, there is still the error with the handler object. How are you disabling this error?

I found out about the error when you pointed it out, it’s not shown in my editor but it is on the playground. Probably because of a different TS config.

Screenshot from 2019-06-13 09-45-35

Screenshot from 2019-06-13 09-46-34

BTW, none of this is an indictment on your code, I’ve just been grappling with the same sort of problem trying to ensure that all our reducers pick up the changes to actions.

Of course 🎉


I’ve been using the handlers inline all the time, so I never had the need, but it really makes sense to extract them. Found a way to do it with ActionsOfType. It’s a bit verbose on the types, so I personally prefer the handlers inline. But hey, it’s possible 🎉

type Handler<State, ActionType extends string, Actions> = 
  (s: State, a: ActionsOfType<Actions, ActionType>) => State

const barHandler: Handler<State, 'bar', Actions> =
  (s, { payload }) => ({n: s.n + payload})

handleActions<State, Types, Actions>(
    {
        foo: (s) => ({n: s.n + 1}),
        bar: barHandler,
    },
    { n: 0},
)

Updated the playground: http://bit.ly/2F1V0Gz

And I think I will add it to the library when I get some time.

EDIT: added Handler to @housinganywhere/safe-redux https://github.com/housinganywhere/safe-redux/pull/4

Read more comments on GitHub >

github_iconTop Results From Across the Web

handleActions returning defaultState even when state passed ...
The first console statement returns the defaultState which is ['red'] whereas the second console statement returns undefined even though they ...
Read more >
Tutorial - redux-actions
Next we are going to handle that action with handleAction . We can provide it our increment action to let it know which...
Read more >
What is the purpose of brackets, [], in handleActions()?
This is a computed object property name notation, introduced in ES6. In a nutshell, it allows you to define objects with variable keys:...
Read more >
redux-actions · Typescript and Webpack
This example will showcase the default implementation using this function. import {Action, handleActions} from 'redux-actions'; // import the ActionTypes and ...
Read more >
Redux-Actions through Example: Part 1 | by John Tucker
We now write a simple React / Redux application using the duck pattern; ... import { createAction, handleActions } from 'redux-actions';// ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found