首页 > 解决方案 > 如何过滤 Redux 操作?

问题描述

是否可以向操作添加更多信息,以便特定于组件的减速器(以及 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,则有可能同时加载多个屏幕。

标签: reactjsreact-nativereduxreact-redux

解决方案


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

它可以类似于:

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等。

UPD

想象一下,你有一个输入状态的 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;
}

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

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'))

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


推荐阅读