我正在尝试学习Redux,所以:我正在通过Action创建者,行动者,减少者,调度员......
现在,我正在尝试学习如何基于其他状态生成x状态。对于这个案子,名字和爱好。
我有类型,const:NAMES
和HOBBIES
,我的动作创建者使用它们将它们作为类型和有效负载返回,例如:{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];
我试图找到解决方案,但我不能。我很欣赏任何帮助,因为我很新。
答案 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
);
这增加了一些开销计算以换取快捷方式