Redux多个动作

时间:2016-10-25 10:51:56

标签: redux

我有2个Firebase侦听器,它们会在数据库更改时发出操作:

export function watchProfile(uid) {
  return dispatch => {
    fb.db.ref(`profiles/${uid}`).on('value', (snapshot) => {
      dispatch({type: constants.UPDATE_PROFILE, payload: snapshot.val()})
    })
    fb.db.ref(`activeEvents/${uid}`).on('child_added', (snapshot) => {
      const eventId = snapshot.key;
      fb.db.ref(`events/${eventId}`).on('value', (snapshot) => {
        dispatch({type: constants.ACTIVE_EVENT, payload: {...snapshot.val(), id: eventId}})
      })
    })
  }
}

此外,还有另一个行动。它进行更改,由上面的两个侦听器检测到。 一旦这个"另一个动作"发出错误,我收到错误:

Reducers may not dispatch actions.

为什么会这样?

应用已构建在pepperoni-app-kit之上 redux-thunk已添加。

如果我向听众dispatch添加超时,那么它运行正常,但当然,这不是解决方案。

case constants.UPDATE_PROFILE:
  return state.set('profile', fromJS(action.payload))
  break;

case constants.SUBMIT_EVENT: {
  const profile = state.get('profile').toJS();
  const eventId = action.payload;
  fb.db.ref(`activeEvents/${profile.uid}/${eventId}`).set(true);
  fb.db.ref(`profiles/${profile.uid}/totalEvents`).set(Number(profile.totalEvents) +1 || 1);
  return state
  break;
}

case constants.ACTIVE_EVENT: {
  if (typeof action.payload === 'string') {
    return state.deleteIn(['activeEvents', action.payload])
  } else {
    return state.setIn(['activeEvents', action.payload.id], action.payload)
  }
}

操作:

SUBMIT_EVENT // the one, which triggers changes in db
UPDATE_PROFILE
ACTIVE_EVENT 

1 个答案:

答案 0 :(得分:0)

查看来源https://github.com/reactjs/redux/blob/55f1d08000b1b064eaa933bbbd132230e53bcccb/src/createStore.js#L165,您似乎遇到此错误,因为您修改了(通过fb.db.ref)WHILE消费操作。这可能会导致您的firebase侦听器触发并发送新操作。

使用setTimeout时它起作用的原因是因为它会在下一个事件循环中最早触发,这意味着就redux而言,你已经完成了处理一个动作并且可以解雇另一个动作。 / p>

修复它的方法可能是编写自己的中间件(请参阅http://redux.js.org/docs/advanced/Middleware.html#seven-examples),它将对constants.SUBMIT_EVENT事件做出反应并对fb.db.ref...进行操作。它会起作用,因为虽然禁止从reducer发送一个动作,但从中间件上下文中可以做到这一点。

请注意循环更新 - 如果您不断更新Firebase中的某个项目,那么将会触发" onUpdate"动作,它将反过来更新Firebase中的项目,您将遇到麻烦。