this.setState 在 Child 中使用 parent 的回调函数时不会更新
this.setState does not update in Child when using a callback function to parent
我有一个 Select 表单 Child 组件,用户可以从中选择多个选项。每次用户做出选择时,都会执行一个函数 handleChange,它从 parent 调用函数 changeExport(作为 prop 传递给 child)。 changeExport 然后更新 parent 状态,handleChange 通过更新 child 状态完成。问题是,如果更新 parent 状态,则不会更新 child 状态,但是如果我注释掉更新 parent 状态的行,则会更新 child 状态就好了。
这是Parent。
class ExtendedTable extends React.Component {
constructor(props) {
super(props)
// columnJSON el format is { title: str, field: str, export: bool }
this.state = { dataJSON: [], columnJSON: [] }
this.changeExport = this.changeExport.bind(this)
}
changeExport(titles){
const newColumnJSON = JSON.parse(JSON.stringify(this.state.columnJSON));
newColumnJSON.forEach(col => {
if (titles.indexOf(col.title) >= 0) {
col.export = true
}
else {
col.export = false
}
})
this.setState({ columnJSON: newColumnJSON })
}
render(){return(
....
<MultipleSelect names={this.state.columnJSON.map(el=>el.title)} export={this.changeExport} />
)}
这是child。
class MultipleSelect extends React.Component {
constructor(props){
super(props)
this.state = {
names:this.props.names,
column:[]}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event){
const arr = event.target.value.slice()
this.setState({column:arr})
this.props.export(arr)
}
render() { return(
<div>
<FormControl>
<InputLabel >Tag</InputLabel>
<Select
multiple
value={this.state.column}
onChange={this.handleChange}
input={<Input />}
renderValue={selected => selected.join(', ')}
MenuProps={MenuProps}
>
{this.state.names.map(col => (
<MenuItem key={col} value={col}>
<Checkbox checked={
this.state.column.indexOf(col) > -1}/>
<ListItemText primary={col} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
)};
}
出于这个原因,您在这里所做的 - 将 props 复制到状态 - warned against in the React documentation。
链接页面提供了多种选择。在你的情况下,我认为你最好通过完全消除状态并完全依赖传入的道具来使 MultipleSelect
成为受控组件。这可能看起来像这样:
class MultipleSelect extends React.Component {
render() {
return (
<div>
<FormControl>
<InputLabel>Tag</InputLabel>
<Select
multiple
value={this.props.selected}
onChange={this.props.handleChange}
input={<Input />}
renderValue={selected => selected.join(", ")}
MenuProps={MenuProps}
>
{this.props.options.map(col => (
<MenuItem key={col} value={col}>
<Checkbox checked={this.props.selected.indexOf(col) > -1} />
<ListItemText primary={col} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
}
我有一个 Select 表单 Child 组件,用户可以从中选择多个选项。每次用户做出选择时,都会执行一个函数 handleChange,它从 parent 调用函数 changeExport(作为 prop 传递给 child)。 changeExport 然后更新 parent 状态,handleChange 通过更新 child 状态完成。问题是,如果更新 parent 状态,则不会更新 child 状态,但是如果我注释掉更新 parent 状态的行,则会更新 child 状态就好了。
这是Parent。
class ExtendedTable extends React.Component {
constructor(props) {
super(props)
// columnJSON el format is { title: str, field: str, export: bool }
this.state = { dataJSON: [], columnJSON: [] }
this.changeExport = this.changeExport.bind(this)
}
changeExport(titles){
const newColumnJSON = JSON.parse(JSON.stringify(this.state.columnJSON));
newColumnJSON.forEach(col => {
if (titles.indexOf(col.title) >= 0) {
col.export = true
}
else {
col.export = false
}
})
this.setState({ columnJSON: newColumnJSON })
}
render(){return(
....
<MultipleSelect names={this.state.columnJSON.map(el=>el.title)} export={this.changeExport} />
)}
这是child。
class MultipleSelect extends React.Component {
constructor(props){
super(props)
this.state = {
names:this.props.names,
column:[]}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event){
const arr = event.target.value.slice()
this.setState({column:arr})
this.props.export(arr)
}
render() { return(
<div>
<FormControl>
<InputLabel >Tag</InputLabel>
<Select
multiple
value={this.state.column}
onChange={this.handleChange}
input={<Input />}
renderValue={selected => selected.join(', ')}
MenuProps={MenuProps}
>
{this.state.names.map(col => (
<MenuItem key={col} value={col}>
<Checkbox checked={
this.state.column.indexOf(col) > -1}/>
<ListItemText primary={col} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
)};
}
出于这个原因,您在这里所做的 - 将 props 复制到状态 - warned against in the React documentation。
链接页面提供了多种选择。在你的情况下,我认为你最好通过完全消除状态并完全依赖传入的道具来使 MultipleSelect
成为受控组件。这可能看起来像这样:
class MultipleSelect extends React.Component {
render() {
return (
<div>
<FormControl>
<InputLabel>Tag</InputLabel>
<Select
multiple
value={this.props.selected}
onChange={this.props.handleChange}
input={<Input />}
renderValue={selected => selected.join(", ")}
MenuProps={MenuProps}
>
{this.props.options.map(col => (
<MenuItem key={col} value={col}>
<Checkbox checked={this.props.selected.indexOf(col) > -1} />
<ListItemText primary={col} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
}