Redux:如何基于其他状态创建状态?

时间:2018-03-14 22:28:55

标签: javascript reactjs redux react-redux

我正在尝试学习Redux,所以:我正在通过Action创建者,行动者,减少者,调度员......

现在,我正在尝试学习如何基于其他状态生成x状态。对于这个案子,名字和爱好。

我有类型,const:NAMESHOBBIES,我的动作创建者使用它们将它们作为类型和有效负载返回,例如:{type:HOBBIES,request:payload} < / p>

然后我有我的reducer文件,我在这两个案例中切换一个动作(和默认的一个)

我从我的主文件App.js发送,并将这些状态作为道具访问。

function mapStateToProps(state) {
  return {
    names: state.names,
    hobbies: state.hobbies
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ grabNames, grabHobbies }, dispatch);
}

export default connect(mapStateToProps,mapDispatchToProps)(myApp);

我正在使用combineReducers(index.js)

const rootReducer = combineReducers({
  names: namereducer,
  hobbies: hobbyreducer
});

目前我有以下redux状态。

names: [
  {name: "A", id: "1"},
  {name: "B", id: "2"},
  {name: "C", id: "3"}
]

hobbies: [
  {basedId: "1", hobby: "cooking"},
  {basedId: "2" hobby: "reading"},
  {basedId: "3" hobby: "gaming"},
{basedId: "1" hobby: "reading"}
]

结果应该是包含每个basedId的爱好的对象数组,当然还有Redux的良好实践。

result: [
      {name: "A", id: "1", hobby: ["cooking", "reading"]},
      {name: "B", id: "2", hobby: "reading"},
      {name: "C", id: "3", hobby: "gaming"}
]

问题是我从未超越简单的地图和[... state,action.data];

我试图找到解决方案,但我不能。我很欣赏任何帮助,因为我很新。

4 个答案:

答案 0 :(得分:1)

还原原则之一是&#34;单一的事实来源&#34;。 它意味着不重复数据,它更有效,并防止许多错误和问题。

但是如果你只想在两个减速器之间共享数据,你可以做到 通过使用redux thunk middleware

基本上,您可以在使用调度启动操作之前从其他Reducer状态读取数据。

简单操作

this

使用thunk采取行动

function myAction() {
  return {
    type: DO_SOMTHING
  };
}

答案 1 :(得分:1)

这是reselect的完美用例。您的代码基本上如下所示:

import { createSelector } from 'reselect';

const namesSelector = state => state.names;
const hobbiesSelector = state => state.hobbies;
const combineNamesAndHobbies = (names, hobbies) =>
  names.map(name => ({
    ...name,
    hobby: hobbies.filter(hobby => hobby.basedId === name.id)
                  .map(hobby => hobby.hobby)
  }));

const resultSelector = createSelector(
  [namesSelector, hobbiesSelector],
  combineNamesAndHobbies
);

function mapStateToProps(state) {
  return {
    names: namesSelector(state),
    hobbies: hobbiesSelector(state),
    result: resultSelector(state)
  }
}

这将导致您的myApp组件具有这些props

{
  names: [
    { name: "A", id: "1" },
    { name: "B", id: "2" },
    { name: "C", id: "3" }
  ],
  hobbies: [
    { basedId: "1", hobby: "cooking" },
    { basedId: "2", hobby: "reading" },
    { basedId: "3", hobby: "gaming" },
    { basedId: "1", hobby: "reading" }
  ],
  result: [
    { name: "A", id: "1", hobby: ["cooking", "reading"] },
    { name: "B", id: "2", hobby: ["reading"] },
    { name: "C", id: "3", hobby: ["gaming"] }
  ]
}

请注意,hobby将始终是一个数组,我认为这是最佳实践。 (但您应该将其命名为hobbies。)

答案 2 :(得分:0)

我认为不会从已存储的数据中生成新状态,因为您将存储两次相同(但已修改)的数据。而是在需要时执行此数据操作并构造您的result对象。

话虽如此,这是你的答案,有点 ES6 香料:

names.map(name => (
   { ...name, hobby: hobbies.filter(hobby => hobby.basedId === name.id).map(hobby => hobby.hobby) } 
))

答案 3 :(得分:0)

我同意@xehpuk。通过使用reselect,如果没有相关状态发生变化,则可以避免重新计算生成的状态,如果多次调用选择器函数(如渲染循环),则非常有用,因此您无需手动优化此部分

要减少所需的代码,您还可以尝试redux-named-reducers并改为编写选择器:

const resultSelector = createSelector(
  [namesModule.names, hobbiesModule.hobbies],
  combineNamesAndHobbies
);

这增加了一些开销计算以换取快捷方式