Adding a callback to a Redux Reducer

2020-06-05 01:12发布

Would there be anything wrong/anti-pattern-ish (in terms of 'thinking-in-react/redux') in added a callback to the action.data passed into an action?

// reducer
ACTION_FOR_REDUCER() {
  var x = 123
  if ( action.data.callback ) action.data.callback( x )
  return {
    something: action.data.somedata
  }
},

Then accessing that data later in the App when the action is called (in an container perhaps)

// later in the app
this.props.dispatch(changeSomething({
  somedata: somedata,
  callback: (x) => { console.log(x) }
}))    

3条回答
做自己的国王
2楼-- · 2020-06-05 01:57

Callbacks introduce side-effects, so when using Redux you should consider returning a new state with the result, for example with done: true flag and react to that in componentDidUpdate.

For managing asynchrony and effects you can use redux-saga, redux-thunk, RxJs or another library. If you want to stick with callbacks, why even bother with Redux?

查看更多
男人必须洒脱
3楼-- · 2020-06-05 02:05

The third principle of Redux (listed in the introduction section of the docs) is that 'changes are made with pure functions'.

A pure function is a function that always returns the same result given the same inputs, and doesn't cause any side effects. Having a callback log something out most definitely would be a side effect!

The docs go on to say:

It's very important that the reducer stays pure. Things you should never do inside a reducer:

  • Mutate its arguments;
  • Perform side effects like API calls and routing transitions;
  • Call non-pure functions, e.g. Date.now() or Math.random().

The reasoning behind this is it makes your reducers predictable - you know that, given an action with a certain payload, you're guaranteed to have the same output. This makes your app both easier to understand as a developer, and easier to unit test.

If you want to perform side effects when an action takes place, you should install a middleware that allows you to do so - some common examples of these are:

  • redux-thunk, which allows you to dispatch functions that can in turn dispatch actions (commonly used to make API calls)
  • redux-logger, which allows you to log out actions that are dispatched.
  • redux-devtools-extension, which allows you to view your state and actions in a Chrome devtools extension.

If you can't find a middleware package that does what you need (rare, to be honest - there's lots out there already!), you can write your own quite easily.

查看更多
手持菜刀,她持情操
4楼-- · 2020-06-05 02:13

The idea is not wrong, the implementation is.

Instead of adding a callback, return a promise from the action (you will need redux-thunk middleware or some similar alternative).

Then you can simply do:

dispatch(myAction).then(callback);

Of course, you can also simply dispatch another action in your callback, which usually end up being one compound action.

const myAction = ...
const callbackAction = ...

const compoundAction = () => dispatch => {
     dispatch(myAction())
         .then(() => dispatch(callbackAction()));
};
查看更多
登录 后发表回答