【问题标题】:How to filter Redux actions?如何过滤 Redux 操作?
【发布时间】:2018-05-23 21:13:27
【问题描述】:

是否可以向操作添加更多信息,以便特定于组件的减速器(以及 sagas/您正在使用的任何副作用库)可以过滤它们?

例子:

function reducerComponentA(state, action) {
  switch (action.type) {
    case START_FETCH:
      return {
        ...state,
        isLoading: true,
      };
      break;

    case START_FETCH_SUCCESS:
      return {
        ...state,
        isLoading: false,
      };
      break;
  }

  return state;
}

function reducerComponentB(state, action) {
  switch (action.type) {
    case START_FETCH:
      return {
        ...state,
        isLoading: true,
      };
      break;

    case START_FETCH_SUCCESS:
      return {
        ...state,
        isLoading: false,
      };
      break;
  }

  return state;
}

注意两个减速器如何观察相同的动作并对其采取行动(显示加载动画)。现在,如果这些减速器相关的屏幕/组件都在内存中,START_FETCH 将导致它们都显示加载动画,甚至可能重叠(因为它是全局的)。按屏幕/组件过滤操作是一个好的解决方案吗?

像这样:

function reducerComponentA(state, action) {
  if (action.currentScreen === 'ScreenA') {
    switch (action.type) {
      ...
    }
  }

  return state;
} 

这似乎是 React Native 的更多问题,因为如果您使用的是 Navigator,则可能会同时加载多个屏幕。

【问题讨论】:

    标签: reactjs react-native redux react-redux


    【解决方案1】:

    您可以将减速器“挂载”到状态的不同部分。为此,您可以将path 添加到操作中,并在reducer 中更新相应的状态切片。

    可能类似于:

    function reducer(state, action) {
      if (action.type === '...') {
        return _.set(_.deepClone(state), `${action.path}.isLoading`, false)
      } else return state;
    }
    

    换句话说,action 决定了 state reducer 的哪一部分将被操作。

    请注意,上面的示例效率极低,仅用于演示目的。与其克隆状态,不如使用一些不变性助手:kolodny/immutability-helpermweststrate/immer、其他。

    更新

    假设你有一个输入状态的 action 和 reducer:

    const UPDATE_VALUE = 'UPDATE_VALUE';
    const updateValue = (value) => ({ type: UPDATE_VALUE, value })
    
    function reducer(state, action) {
      if (action.type === UPDATE_VALUE) {
        return { ...state, input: action.value }
      } else return state;
    }
    

    并且您想将此动作/reducer 用于许多不同的输入。该动作可以提供 一个属性路径,指示应该更新哪个部分或状态,以及最终哪个输入 将收到新的道具:

    const UPDATE_VALUE = 'UPDATE_VALUE';
    const updateValue = (value, path) => ({ type: UPDATE_VALUE, value, path })
    
    function reducer(state, action) {
      if (action.type === UPDATE_VALUE) {
        return { ...state, [action.path]: action.value }
      } else return state;
    }
    

    这时候就可以用了:

    dispatch(updateValue(event.target.value, 'firstNameInput'))
    dispatch(updateValue('Doe', 'lastNameInput'))
    

    答案开头的代码是后者的通用版本。

    【讨论】:

    • 我不确定我是否理解您的解决方案,您能详细说明一下吗?
    • 当然,我会写一个例子
    • 我不认为这真的是我遇到的问题,而且这似乎不是一个好习惯(毕竟,你要离开组件/容器知道如何更新状态,而不是 reducer)。
    猜你喜欢
    • 2019-06-03
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多