Javascript 反应问题-子状态更改父状态

Javascript 反应问题-子状态更改父状态,javascript,reactjs,ecmascript-6,material-ui,Javascript,Reactjs,Ecmascript 6,Material Ui,问题: 如果每个组件都有自己的状态,那么这件事是如何发生的, 孩子可能正在改变父母的状态 以下是我的应用程序的完整代码: 以下是stackblitzworking联机代码的链接: 如何生成问题: 从第一个文本框中选择车辆1 从第二个文本框中选择车辆2 从第三个文本框中选择车辆3 你会明白的。你的问题是,在子组件中,你正在改变父状态。当您更改vehicles数组中项目的选定属性时,会在行中发生此情况: 变异是传播到所有AutoCompleteHlpr组件的方法,因为您将相同的数组传递给所有组件。您

问题:

如果每个组件都有自己的状态,那么这件事是如何发生的, 孩子可能正在改变父母的状态

以下是我的应用程序的完整代码:

以下是stackblitzworking联机代码的链接:

如何生成问题:

从第一个文本框中选择车辆1 从第二个文本框中选择车辆2 从第三个文本框中选择车辆3
你会明白的。

你的问题是,在子组件中,你正在改变父状态。当您更改vehicles数组中项目的选定属性时,会在行中发生此情况:

变异是传播到所有AutoCompleteHlpr组件的方法,因为您将相同的数组传递给所有组件。您造成的情况是,实际上所有AutoCompleteHlpr组件都有一个全局状态

要修复此问题,您需要通过车辆阵列的克隆,这样更改克隆对象上的道具不会影响原始道具。下面是一个简单的克隆实现,但您可以使用lodash等的另一个克隆实现:

const clone = (arg) => JSON.parse(JSON.stringify(arg));
在代码中,您可以这样使用它:

<AutoCompleteHlpr 
          dataSource={clone(this.state.vehicles)} 
          dataSourceConfig={dataSourceConfig}
          floatingLabelText='Select Vehicles'
          selectedOption={this.handleSelectedVehicle}/>
您可以执行以下操作:

const newDataSource = this.state.dataSource.reduce((ds, item, idx) => index !== idx
   ? ds.concat(item)
   : ds.concat(Object.assign({}, item, { selected: true })), []);
this.setState({ dataSource: newDataSource, searchText: '' }); 
编辑:查看下面的代码段,了解为什么传递[…this.state.vehicle]无效:

const vehicles=[{value:1,label:'Vehicle 1'},{value:2,label:'Vehicle 2'},{value:3,label:'Vehicle 3'},{value:4,label:'Vehicle 4'},{value:5,label:'Vehicle 5'},{value:6,label:'Vehicle 6'},{value:7,label:'Vehicle 7'},{value:8,label:'Vehicle 8'}; 常数车辆2=[…车辆]; console.logvehicles===车辆2; 控制台.logvehicles[0]==vehicles2[0];
console.logvehicles.everyitem,idx=>item===vehicles2[idx]您正在传递一个引用,因此子组件可以从父组件访问相同的vehicles数组

<AutoCompleteHlpr 
          dataSource={this.state.vehicles} 
          dataSourceConfig={dataSourceConfig}
          floatingLabelText='Select Vehicles'
          selectedOption={this.handleSelectedVehicle}
/>

您不应该对其进行变异,因此我建议使用Object.assign[],[this.state.vehicles],如果它没有嵌套下来,或者使用不会破坏的slice,只在dataSource属性中传递它的一个副本,如so dataSource=this.state.vehicles.slice,还有JSON.parseJSON.stringifysomeobject选项,这是最好的选项,因为slice和Object.assign都提供原始对象的浅拷贝。您还可以查看帮助程序库,如lodash等


注意:所有状态操作只能使用文档中所述的this.setState进行。检查您的请求方法。

请在问题中包含您的代码。我不知道这个stackblitz网站是什么,我也不打算访问它,访问这个问题的大多数人也不会访问它。@JamesDonnelly,请访问它一次它的plunkr类型,在这个网站上我创建了整个问题的演示,在那里你可以看到整个项目代码。问题是,如果该网站宕机或因任何原因无法访问,这个问题将变得毫无意义。是的,如果你做了post代码,这是很有帮助的,最终你将需要这样做,不管怎样,你对每个字段使用相同的状态来保存值。在您将值保存到同一位置之前,没有其他方法可以工作。好的,它可以工作,我也尝试过,所以您正在做的是传递车辆的克隆,所以我也可以在es6样式中执行{…车辆},对吗?我还将变异行替换为var data_source=this.state.dataSource;数据源[索引]['selected']=true;那么它应该能正常工作?但不起作用这不是真的,一旦我们将数据传递给子组件,它将保持自己的状态,然后它将如何更改父组件的状态?如果只传递[…this.state.vehicles],它将不起作用,因为它将引用与this.state.vehicles中相同的对象。您需要传递深层克隆,但这样做只会生成浅层copyvar data\u source=this.state.dataSource;data_source[index]['selected']=true这将不起作用,因为您再次只是重新分配数组,所以您仍然在变异this.state.datasource=this.state.vehicles.slice,不起作用我已经解释了为什么Object.assign[],[this.state.vehicles]并且dataSource=this.state.vehicles.slice不会work@AndrzejSmyk如果状态被正确操纵,为什么它们不工作?如果你没有改变数组项,它应该工作得很好then@AndrzejSmyk不知道你的意思,问题是孩子怎么会改变父母的状态。除了Object.assign可能存在深层嵌套问题外,这些方法都能很好地工作。是否改变数组项与问题无关@VivekDoshi如果您指的是上面的代码片段,那是因为您正在直接改变状态,并且在父级中缺少handleSelectedVehicle方法
this.state.dataSource[index]['selected'] = true;
const newDataSource = this.state.dataSource.reduce((ds, item, idx) => index !== idx
   ? ds.concat(item)
   : ds.concat(Object.assign({}, item, { selected: true })), []);
this.setState({ dataSource: newDataSource, searchText: '' }); 
<AutoCompleteHlpr 
          dataSource={this.state.vehicles} 
          dataSourceConfig={dataSourceConfig}
          floatingLabelText='Select Vehicles'
          selectedOption={this.handleSelectedVehicle}
/>