- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题:
如果每个组件都有自己的状态,那么这件事情是怎么发生的,怎么可能 child 正在改变 parent 的状态?
这是我的应用的完整代码:
import React, { Component } from 'react';
import { render } from 'react-dom';
import AutoComplete from 'material-ui/AutoComplete';
import Chip from 'material-ui/Chip';
import Hello from './Hello';
import './style.css';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
class App extends Component {
constructor() {
super();
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'}];
this.state = {
vehicles,
name: 'React',
name1: 'React1',
name2: 'React2'
};
}
render() {
const dataSourceConfig = {
text: 'label',
value: 'value',
};
return (
<div>
<MuiThemeProvider>
<div>
<AutoCompleteHlpr
dataSource={this.state.vehicles}
dataSourceConfig={dataSourceConfig}
floatingLabelText='Select Vehicles'
selectedOption={this.handleSelectedVehicle}/>
<AutoCompleteHlpr
dataSource={this.state.vehicles}
dataSourceConfig={dataSourceConfig}
floatingLabelText='Select Vehicles'
selectedOption={this.handleSelectedVehicle}/>
<AutoCompleteHlpr
dataSource={this.state.vehicles}
dataSourceConfig={dataSourceConfig}
floatingLabelText='Select Vehicles'
selectedOption={this.handleSelectedVehicle}/>
</div>
</MuiThemeProvider>
<Hello name={this.state.name} />
<p>
Start editing to see some magic happen :)
</p>
</div>
);
}
}
export class AutoCompleteHlpr extends React.Component {
constructor(props) {
super(props);
this.state = {dataSource : this.props.dataSource , searchText : ''};
this.styles = {
chip: {
margin: 4,
},
wrapper: {
display: 'flex',
flexWrap: 'wrap',
},
};
this.handleNewRequest = this.handleNewRequest.bind(this);
this.getDataSource = this.getDataSource.bind(this);
console.log(this.state);
}
handleNewRequest(searchText , index){
this.state.dataSource[index]['selected'] = true;
this.setState({dataSource : this.state.dataSource , searchText : '' });
this.props.selectedOption(this.state.dataSource[index] , this.state.dataSource);
}
renderChip(data , index) {
if(data.selected) {
var value = this.props.dataSourceConfig.text ? this.props.dataSourceConfig.text : 'text';
var key = this.props.dataSourceConfig.value ? this.props.dataSourceConfig.value : 'value';
return (
<Chip
key={data[key]}
style={this.styles.chip}
onRequestDelete={() => this.handleRequestDelete(index)} >
{data[value]}
</Chip>
);
}
}
handleRequestDelete(index) {
this.state.dataSource[index]['selected'] = false;
this.setState({dataSource : this.state.dataSource , searchText : '' });
this.props.selectedOption(this.state.dataSource[index] , this.state.dataSource);
}
componentWillReceiveProps(nextProps) {
if(this.props.dataSource !== nextProps.dataSource) {
this.setState({ dataSource : nextProps.dataSource });
}
}
getDataSource() {
return this.state.dataSource.map(data => {
if(!data.selected) {
return data
}
})
}
render() {
return(
<div>
<AutoComplete
floatingLabelText={this.props.floatingLabelText}
filter={AutoComplete.caseInsensitiveFilter}
onNewRequest={this.handleNewRequest}
searchText={this.state.searchText}
dataSource={this.getDataSource()}
dataSourceConfig={this.props.dataSourceConfig}
openOnFocus={true}
/>
<div style={this.styles.wrapper}>
{this.state.dataSource.map(this.renderChip, this)}
</div>
</div>
)
}
}
AutoCompleteHlpr.defaultProps = {
floatingLabelText : 'Type Something',
dataSource : [],
dataSourceConfig : {},
selectedOption: () => { }
};
render(<App />, document.getElementById('root'));
这是 stackblitz(在线工作代码)的链接:
https://stackblitz.com/edit/react-svqwcg
如何生成问题:
你会明白的。
最佳答案
您的问题是在子组件中您正在改变父状态。当您更改 vehicles
数组中项目的 selected
属性时,它会在线上发生:
this.state.dataSource[index]['selected'] = true;
突变会传播到所有 AutoCompleteHlpr
组件,因为您将同一个数组传递给所有组件。您造成的情况实际上是所有 AutoCompleteHlpr
组件都有一个全局状态。
要解决这个问题,您需要传递 vehicles
数组的克隆,这样更改克隆对象的 Prop 将不会影响原始对象。下面是简单的克隆实现,但您可以使用来自 lodash 等的另一个实现:
const clone = (arg) => JSON.parse(JSON.stringify(arg));
在您的代码中,您可以这样使用它:
<AutoCompleteHlpr
dataSource={clone(this.state.vehicles)}
dataSourceConfig={dataSourceConfig}
floatingLabelText='Select Vehicles'
selectedOption={this.handleSelectedVehicle}/>
另一种选择是,不要像
那样改变selected
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: '' });
编辑:看看下面的代码片段,看看为什么传递 [...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'}];
const vehicles2 = [...vehicles];
console.log(vehicles === vehicles2);
console.log(vehicles[0] === vehicles2[0]);
console.log(vehicles.every((item, idx) => item === vehicles2[idx]))
如您所见,vehicle
和 vehicle2
是不同的数组,但它们的项是对相同对象的引用!这就是您需要深度克隆的原因。
关于javascript - React Issue - 子状态更改父状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46686498/
我有这个 html 代码: HELLO WORLD! X V HELLO WORLD! X V 我想按 X(类关闭)将父 div 的高度更改为 20px 并显示 V(类打开),但在每个 d
在会计应用程序的许多不同实现中,有两种主要的数据库设计方法来保存日志和分类帐数据。 只保留 Journal 信息,然后 Ledger 只是 Journal 的一个 View (因为 journal 总
我想在另一个子里面有一个子, sub a { sub b { } } 我想为每次调用 sub b 创建一个新的 sub a 实例。有没有办法在 Perl 中做到这一点? 当我运行上面的
我有一些代码正在查找重复项并突出显示单元格: Private Sub cmdDups_Click() Dim Rng As Range Dim cel As Range Set Rng = ThisW
可能有一个简单的解决方案,但我很难过。 我有一个包含一个 ID 字段的主表。在两个可能的字段中有一个具有该 ID 的子表。想象一个由选手 A 和选手 B 组成的 double 队。Master 表将有
假设我有一个包含对象的数组: [ { "id": "5a97e047f826a0111b754beb", "name": "Hogwarts", "parentId": "
我正在尝试对 MySQL 数据库表执行一对父/子模型的批量插入,但似乎无法使用标准的 ActiveRecord 功能来完成。所以,我尝试了 activerecord-import gem,但它也不支持
我有一个带有多个子类的父抽象类。最终,我希望通过 GUI 中的进度条显示子类中完成的进度。 我目前所做的,我意识到这是行不通的,是在父类中声明为每个子类将覆盖的虚拟方法的事件方法定义。所以像: pub
是否可以通过键数组在对象中设置变量?例如我有这个对象: var obj = {'outer': {'inner': 'value'} }; 并希望设置由键数组选择的值: var keys = ['ou
我有一个名为 companies 的 MySQL 表,如下所示: +---------+-----------+-----------+ | id_comp | comp_name | id_pare
我正在尝试使用 sublime text 在 sublime text 上的 ionic 上打开我的第一个应用程序。它给了我一个“找不到命令”的错误。如何修复? 我试过这些命令: sudo rm -r
不好意思问,但我正在使用 webapp2,我正在设计一个解决方案,以便更容易定义路由 based on this google webapp2 route function .但这完全取决于能够在子级
我有代表树的数字字符串(我不知道是否有官方名称): 012323301212 上面的例子代表了 2 棵树。根用 0 表示。根的直接子代为“1”,“1”的直接子代为“2”,依此类推。我需要将它们分组到由
是否可以在当前 Activity 之上添加 Activity 。例如,假设我单击一个按钮,然后它将第二个 Activity 添加到当前 Activity 。而第二个 Activity 只覆盖了我当前
我很难思考如何为子资源建模。 以作者的书籍为例。你可以有 N 本书,每本书只有一位作者。 /books GET /books POST /books/id PUT /books/id DELETE 到
有人可以向我解释以下内容(python 2.7) 来自已解析文件的两个字符串数字: '410.9''410.9 '(注意尾随空格) A_LIST = ['410.9 '] '410.9' in '41
背景 在 PowerShell 中构建 hash table 是很常见的通过特定属性快速访问对象,例如以 LastName 为基础建立索引: $List = ConvertFrom-Csv @' I
我真的很难弄清楚如何调用嵌套 Polymer Web 组件的函数。 这是标记: rise-distribution组件有 canPlay我想从 rise-playlist
我写了一个小工具转储(以 dot 格式)一个项目的依赖关系图,其中所有位于同一目录中的文件都聚集在一个集群中。当我尝试生成包含相应图形的 pdf 时,dot开始哭: 命令 dot -Tpdf trim
给定一个 CODE ref,是否可以: 访问该 CODE ref 的解析树 通过指定 CODE ref 的解析树来创建一个新的 CODE ref,该解析树可以包含在 1 中返回的解析树的元素 通常我们
我是一名优秀的程序员,十分优秀!