javascript - 如何取消/忽略 redux 中的操作

标签 javascript flux redux

有没有办法取消或忽略一个 Action ?

或者更确切地说,忽略操作的最佳/推荐方法是什么?

我有以下 Action 创建器,当我向 Action 创建器输入无效大小(例如 'some_string')时,除了收到我自己的警告消息外,我还收到: Uncaught Error :操作必须是普通对象。使用自定义中间件进行异步操作。

import { SET_SELECTED_PHOTOS_SIZE } from './_reducers';

export default (size=0) => {
  if (!isNaN(parseFloat(size))) {
    return {
      type: SET_SELECTED_PHOTOS_SIZE,
      size: size,
    };
  } else {
    app.warn('Size is not defined or not a number');
  }
};

我在 Discord (reactiflux) 的 redux channel 中讨论过这个问题,其中一个建议是像这样使用 redux-thunk:

export default size => dispatch => {
  if (!isNaN(parseFloat(size))) {
    dispatch({
      type: SET_SELECTED_PHOTOS_SIZE,
      size: size,
    });
  } else {
    app.warn('Size is not defined or not a number');
  }
}

另一种选择是忽略 reducer 内部的 Action 。这确实让 reducer 变得“更胖”,因为它承担了更多的责任,但它使用的 thunk-actions 更少,这使得它更容易调试。我可以看到 thunk 模式失控,因为我将被迫在几乎每个 Action 中使用它,如果你有很多批处理 Action ,维护起来会有点痛苦。

最佳答案

忽略 Action 创建器中的 Action 基本上是一种将它们视为命令处理程序而不是事件创建器的方式。当用户点击按钮时,它是某种事件。

所以基本上有两种方法可以解决这个问题:

  1. 条件在 action creator 内部,使用 thunk-middleware

    const cancelEdit = () => (dispatch, getState) => {
      if (!getState().isSaving) {
        dispatch({type: CANCEL_EDIT});
      }
    }
    
  2. 条件在reducer内部,不需要中间件

    function reducer(appState, action) {
      switch(action.type) {
       case: CANCEL_EDIT:
         if (!appState.isSaving) {
           return {...appState, editingRecord: null }
         } else {
           return appState;
         }
       default:
         return appState;
    
      }
    }
    

我非常喜欢将 UI 交互视为事件而不是命令,这有两个优点:

  1. 您所有的域逻辑都保留在非常容易测试的同步纯 reducer 中。试想一下,您需要为功能编写单元测试。

    const state = {
      isSaving: true,
      editingRecord: 'FOO'
    };
    
    // State is not changed because Saving is in progress
    assert.deepEqual(
      reducer(state, {type: 'CANCEL_EDIT'}),
      state
    );
    
    // State has been changed because Saving is not in progress anymore
    assert.deepEqual(
      reducer({...state, isSaving: false}),
      {isSaving: false, editingRecord: null}
    );
    

如您所见,当您将交互视为事件时,测试真的很简单

  1. 如果您决定与其忽略该操作,不如显示一些视觉指示来表明该操作是不可能的,该怎么办?您将需要分派(dispatch)另一个 Action 或基本上重建它。但是,您不能在此处使用带重放的热重载,因为 action creator 中的逻辑不可重放。如果逻辑在 reducer 中,你可以简单地改变行为,reducer 将被热重载并且所有事件都被重播。您发送的唯一事件是用户单击了某个按钮,您不能否认这一事实。因此,除非您彻底更改 UI,否则您始终可以通过重播进行热重载。

当您将与 UI 的任何交互视为事件时,您将获得最佳的重播体验,因为不能否认事件刚刚发生。

关于javascript - 如何取消/忽略 redux 中的操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34184677/

相关文章:

reactjs-flux - View 应该直接调用商店吗?

javascript - 回流: How to listen to a subset of actions using `listanables` or `this.listenToMany` ?

android - 如何在 React Native 应用程序中维护 session ?

reactjs - React + Redux 在模块/域之间共享操作

javascript - var 在 Foundation.util.touch.js 中未定义

javascript - jquery如何调用另一个函数的 'end'中的函数?

表单验证后Javascript激活弹出窗口

javascript - 如何使用php重定向按钮点击

javascript - 访问容器中的Reducer返回未定义

javascript - 为什么 setTimeout 不适用于 React Redux 中的异步操作创建者?