redux-thunk 调度事件

redux-thunk dispatch events

一些前言,请参阅this post了解我是如何实现条码扫描器的。长话短说,当条形码被扫描时,它在 jQuery 中触发了一个事件,这允许我在我的组件中执行以下操作:

class EmployeeScreen extends Component {
  componentDidMount() {
    $(window).on('barcodeScan', (e) => {
      if ( e.state.type !== 'E' ) {
        alert('Please scan your employee badge');
      } else {
        this.setState({
          badge: e.state.code
        });
      }
    });
  }
}

这很好,因为我能够在这个特定组件上检查员工徽章并显示错误。现在,我正在切换到 redux 风格,但我很难找到解决这个问题的最佳方法。我认为最好的开始方式是使用 redux-thunk 启动 BARCODE_READ 操作:

dispatch({
  type: BARCODE_READ,
  event: {
    type: this.barcodeRead.substr(0, 1),
    code: this.barcodeRead.substr(1),
  }
}));

问题是,我的应用中的多个减速器需要监听 BARCODE_READ,并执行不同的操作。例如,假设我有以下屏幕:

因为此操作是我的全局应用程序操作的一部分,所以我不确定如何将其应用于单个屏幕操作。一种方法是从我的 employee reducer 派发操作,但是 我读到这是一个反模式:

const reducer = (state = initialState, action) => {
    switch (action.type) {
        case BARCODE_READ:
            if (action.event.type === 'E') {
              dispatch({type: 'FETCH_EMPLOYEE_RECORD'});
            }
            return state;
        case FETCH_EMPLOYEE_SUCCESS:
            return {
                ...state,
                employee: action.employee,
            };
        default: {
            return state;
        }
    }
};

我的 supervisor reducer 可能会调度 FETCH_SUPERVSIOR_RECORD,并且视图应该 process/update 相应。因为这是一种反模式(事实上我无权从减速器进行调度),推荐的方法是什么?

这个案例是为 Redux-Observable.

这样的副作用处理中间件量身定做的

你的 reducer 应该做的就是采取行动并 return 状态的新副本。

任何时候您与外部服务(EG REST API、数据库)交互或执行一项长时间的 运行 工作,您都希望在 reducer 之外进行。您可以从您的组件发送自定义操作,并让您的 'epic'(Redux-Observable 处理程序)监听该操作。

另一个类似的库是 Redux-Saga,两者做的事情基本相同。

缩减器不应该触发新动作是正确的。减速器应该只改变应用程序的状态而没有其他副作用。

正确的处理方法是在您的 actionCreator 中。由于您使用的是 redux thunk,我猜您的条形码读取动作创建器看起来像这样:

function barcodeRead() {
  return dispatch => {
    dispatch({
      type: BARCODE_READ,
      event: {
        type: this.barcodeRead.substr(0, 1),
        code: this.barcodeRead.substr(1),
      }
    }));
  };
}

这是执行业务逻辑的地方!以下是一些关于您的新动作创建器外观的伪代码:

function barcodeRead() {
  return dispatch => {
    dispatch({
      type: BARCODE_READ,
      event: {
        type: this.barcodeRead.substr(0, 1),
        code: this.barcodeRead.substr(1),
      }
    }));
   if(employeeScreenShowing) {
     dispatch(updateEmployeeScreen));
   }
  };
}