Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/423.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Redux:如何基于其他状态创建状态?_Javascript_Reactjs_Redux_React Redux - Fatal编程技术网

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

Javascript Redux:如何基于其他状态创建状态?,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,我正在努力学习Redux,所以:我正在经历动作创建者、动作、还原者、调度者 现在,我正在尝试学习如何基于其他状态生成x状态。就这个例子来说,名字和爱好 我有类型,const:名称和业余爱好,我的动作创建者使用它们作为类型和负载返回,例如:{类型:业余爱好,请求:负载} 然后我有了我的reducer文件,我在其中通过一个动作切换这两种情况(以及默认情况) 我从主文件App.js中发送消息,并作为道具访问这些状态 function mapStateToProps(state) { return

我正在努力学习Redux,所以:我正在经历动作创建者、动作、还原者、调度者

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

我有类型,const:
名称
业余爱好
,我的动作创建者使用它们作为类型和负载返回,例如:{类型:业余爱好,请求:负载}

然后我有了我的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);
我正在使用combinereducer(index.js)

目前我有以下redux状态

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

结果应该是一个包含每个
basedId
爱好的对象数组,当然要遵循Redux的良好实践

result: [
      {name: "A", id: "1", hobby: ["cooking", "reading"]},
      {name: "B", id: "2", hobby: "reading"},
      {name: "C", id: "3", hobby: "gaming"}
]
问题是我从未超越简单的地图和[…状态,动作,数据]


我试图找到解决这个问题的办法,但我做不到。我真的非常感谢您的帮助,因为我是一个新手。

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

话虽如此,以下是您的答案,略带一点ES6情趣:

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

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

话虽如此,以下是您的答案,略带一点ES6情趣:

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

重复原则之一是“真理的单一来源”。 这意味着不复制数据,它更有效,并防止了许多错误和问题

但如果您只想在两个减缩器之间共享数据,您可以这样做 通过使用

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

简单操作

function myAction() {
  return {
    type: DO_SOMTHING
  };
}
用thunk进行操作

function myAction() {
  return (dispatch, getState) => {

    // get state contains all existing reducers states
    const { reducerTwo } = getState(); 

    dispatch({
      type: DO_SOMTHING,
      data: reducerTwo.prop
     });
  };
}

重复原则之一是“真理的单一来源”。 这意味着不复制数据,它更有效,并防止了许多错误和问题

但如果您只想在两个减缩器之间共享数据,您可以这样做 通过使用

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

简单操作

function myAction() {
  return {
    type: DO_SOMTHING
  };
}
用thunk进行操作

function myAction() {
  return (dispatch, getState) => {

    // get state contains all existing reducers states
    const { reducerTwo } = getState(); 

    dispatch({
      type: DO_SOMTHING,
      data: reducerTwo.prop
     });
  };
}

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

从“重新选择”导入{createSelector};
const namesSelector=state=>state.names;
const hobbiesSelector=state=>state.cabbies;
const combineNamesand嗜好=(姓名、嗜好)=>
names.map(name=>({
名称
嗜好:嗜好.filter(嗜好=>hobby.basedId===name.id)
.map(hobby=>hobby.hobby)
}));
const resultSelector=createSelector(
[名称选择器,霍布斯选择器],
结合爱好和爱好
);
函数MapStateTops(状态){
返回{
名称:名称选择器(状态),
爱好:霍布斯(州),
结果:结果选择器(状态)
}
}
这将导致您的
myApp
组件具有以下
道具

{
姓名:[
{name:“A”,id:“1”},
{姓名:“B”,id:“2”},
{姓名:“C”,id:“3”}
],
爱好:[
{basedId:“1”,爱好:“烹饪”},
{basedId:“2”,爱好:“阅读”},
{basedId:“3”,爱好:“游戏”},
{basedId:“1”,爱好:“阅读”}
],
结果:[
{姓名:“A”,身份证:“1”,爱好:[“烹饪”,“阅读”]},
{姓名:“B”,身份证:“2”,爱好:[“阅读”]},
{姓名:“C”,身份证:“3”,爱好:[“游戏”]}
]
}

<>请注意<代码>爱好> /代码>永远是一个数组,我认为这是最佳实践。(但是你应该把它命名为
嗜好

这是一个完美的应用案例。您的代码基本上如下所示:

从“重新选择”导入{createSelector};
const namesSelector=state=>state.names;
const hobbiesSelector=state=>state.cabbies;
const combineNamesand嗜好=(姓名、嗜好)=>
names.map(name=>({
名称
嗜好:嗜好.filter(嗜好=>hobby.basedId===name.id)
.map(hobby=>hobby.hobby)
}));
const resultSelector=createSelector(
[名称选择器,霍布斯选择器],
结合爱好和爱好
);
函数MapStateTops(状态){
返回{
名称:名称选择器(状态),
爱好:霍布斯(州),
结果:结果选择器(状态)
}
}
这将导致您的
myApp
组件具有以下
道具

{
姓名:[
{name:“A”,id:“1”},
{姓名:“B”,id:“2”},
{姓名:“C”,id:“3”}
],
爱好:[
{basedId:“1”,爱好:“烹饪”},
{basedId:“2”,爱好:“阅读”},
{basedId:“3”,爱好:“游戏”},
{basedId:“1”,爱好:“阅读”}
],
结果:[
{姓名:“A”,身份证:“1”,爱好:[“烹饪”,“阅读”]},
{姓名:“B”,身份证:“2”,爱好:[“阅读”]},
{姓名:“C”,身份证:“3”,爱好:[“游戏”]}
]
}

<>请注意<代码>爱好> /代码>永远是一个数组,我认为这是最佳实践。(但是你应该把它命名为业余爱好。)

我同意@xehpuk。通过使用,可以避免在相关状态未发生任何更改时重新计算生成的状态,这在多次调用选择器函数(如在渲染循环中)时非常有用,因此无需手动优化此部分

为了减少所需的代码,您也可以尝试这样编写选择器:

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

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

我同意@xehpuk。通过使用,可以避免在相关状态未发生任何更改时重新计算生成的状态,这在多次调用选择器函数时非常有用