问题 React / redux,显示多个组件,共享相同的操作,但具有不同的状态


假设我有一个可重复使用的容器。它是一个包含多个页面的向导。

向导状态由redux / actions驱动。当一个动作被触发时,我使用一个reducer来更新我的状态。

如果我想让多个向导重复,并且具有自己的状态,该怎么办?

我认为必须有一种方法可以让某个动态reducer(可以创建/销毁)处理动作,然后让每个单独的向导从这些动态的store / state中驱动。

这是推荐的吗?这些库是否更容易?


8170
2018-03-30 08:05


起源



答案:


只需根据需要将主状态划分为多个向导状态,并发送向导ID以及每个操作,以便减速器知道要处理哪个。

作为数组

{
  wizards: [
    { id: 'A', state: true },
    { id: 'B', state: false },
    { id: 'C', state: true }
  ]
}

您可以编写向导reducer,了解如何减少单个向导状态。

function wizardReducer(wizard, action) {
  switch(action) {
    case 'TOGGLE':
      return {
        id: wizard.id,
        state: !wizard.state
      };
    default:
      return wizard;
  }
}

然后写一个 wizardsReducer 了解如何减少向导列表。

function wizardsReducer(wizards, action) {
  return wizards.map(function(wizard) {
    if(action.id == wizard.id) {
      return wizardReducer(wizard, action);
    } else {
      return wizard;
    }
  });
}

最后,使用 combineReducers 创建一个委托责任的root reducer wizards 这个属性 wizardsReducer

combineReducers({
  wizards: wizardsReducer
});

作为对象

如果您将向导存储在对象中,则必须构建自己的向导 wizardsReducer 略有不同。

{
  wizards: {
    A: { id: 'A', state: true },
    B: { id: 'B', state: false },
    C: { id: 'C', state: true }
  }
}

当我们可以直接选择我们需要的状态时,映射状态没有多大意义。

function wizardsReducer(wizards, action) {
  if(!(action.id in wizards)) return wizards;

  const wizard = wizards[action.id];
  const updatedWizard = wizardReducer(wizard, action);

  return {
    ...wizards,
    [action.id]: updatedWizard
  };
}

9
2018-03-30 08:23



我的反应组件应该生成唯一ID吗?我在哪里存储/范围ID?在组件的状态?我是否应该在组件的安装/卸载中触发CREATE / DESTROY操作? - Paul Knopf
大多数问题取决于应用程序中各个向导的生命周期和目的。如果向导状态和向导组件之间存在真正的1 - 1关系,那么所有这些建议听起来都合理。 - Dan Prince
我找到了一个很好的redux库,可能会让它变得更简单一些。那里还有其他人。 github.com/tonyhb/redux-ui - Paul Knopf


答案:


只需根据需要将主状态划分为多个向导状态,并发送向导ID以及每个操作,以便减速器知道要处理哪个。

作为数组

{
  wizards: [
    { id: 'A', state: true },
    { id: 'B', state: false },
    { id: 'C', state: true }
  ]
}

您可以编写向导reducer,了解如何减少单个向导状态。

function wizardReducer(wizard, action) {
  switch(action) {
    case 'TOGGLE':
      return {
        id: wizard.id,
        state: !wizard.state
      };
    default:
      return wizard;
  }
}

然后写一个 wizardsReducer 了解如何减少向导列表。

function wizardsReducer(wizards, action) {
  return wizards.map(function(wizard) {
    if(action.id == wizard.id) {
      return wizardReducer(wizard, action);
    } else {
      return wizard;
    }
  });
}

最后,使用 combineReducers 创建一个委托责任的root reducer wizards 这个属性 wizardsReducer

combineReducers({
  wizards: wizardsReducer
});

作为对象

如果您将向导存储在对象中,则必须构建自己的向导 wizardsReducer 略有不同。

{
  wizards: {
    A: { id: 'A', state: true },
    B: { id: 'B', state: false },
    C: { id: 'C', state: true }
  }
}

当我们可以直接选择我们需要的状态时,映射状态没有多大意义。

function wizardsReducer(wizards, action) {
  if(!(action.id in wizards)) return wizards;

  const wizard = wizards[action.id];
  const updatedWizard = wizardReducer(wizard, action);

  return {
    ...wizards,
    [action.id]: updatedWizard
  };
}

9
2018-03-30 08:23



我的反应组件应该生成唯一ID吗?我在哪里存储/范围ID?在组件的状态?我是否应该在组件的安装/卸载中触发CREATE / DESTROY操作? - Paul Knopf
大多数问题取决于应用程序中各个向导的生命周期和目的。如果向导状态和向导组件之间存在真正的1 - 1关系,那么所有这些建议听起来都合理。 - Dan Prince
我找到了一个很好的redux库,可能会让它变得更简单一些。那里还有其他人。 github.com/tonyhb/redux-ui - Paul Knopf


OP要求提供一个lib,所以我只是把它扔到这里。

我创建了infra函数,它将拦截动作并添加 meta-data 每个动作。 (以下 FSA) 您可以轻松地使用它来创建多个容器,而不会相互影响。

减速动作拦截 


0
2018-01-21 08:58