[英]onChange of <select> element in child component not re-rendering the parent state in React, Warning: unmounted component
I'm lifting state up from child to parent and trying to render select elements with data from HTTP request. 我将状态从子级提升到父级,并尝试使用HTTP请求中的数据呈现选择元素。 The select tag values within the
Inv
child component will show previously selected values, but I'm getting this error: Inv
子组件中的选择标记值将显示以前选择的值,但是出现此错误:
Warning: Can't call setState (or forceUpdate) on an unmounted component.
警告:无法在已卸载的组件上调用setState(或forceUpdate)。 This is a no-op, but it indicates a memory leak in your application.
这是空操作,但它表明应用程序中发生内存泄漏。 To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
要解决此问题,请在componentWillUnmount方法中取消所有订阅和异步任务。
It looks like the error is coming from the Inv
child component that is being passed props with this.state.identInvsData
. 看起来错误来自
Inv
子组件,该子组件正在使用this.state.identInvsData
传递给道具。 That is the only time I get the error. 那是我唯一的错误。 The child components in the else statements that don't get the
identInvsData
don't get that error message. else语句中未获得
identInvsData
的子组件不会获得该错误消息。 The parent component does not re-render, or "mount" the children. 父组件不会重新渲染或“装载”子组件。
Any ideas as to what I'm doing wrong? 关于我在做什么错的任何想法吗?
Edit: The child components are populating the data from HTTP endpoint, but onChange it doesn't change the values in
setState
, only when I select the buttonAdd Inv
.编辑:子组件正在从HTTP端点填充数据,但是onChange不会更改
setState
的值,只有当我选择按钮Add Inv
。 It adds another child but also allows the previous children to change.它添加了另一个孩子,但也允许以前的孩子进行更改。
Identity Parent Component 身份父组件
class Identity extends React.Component {
state = {
invIds: [],
inTypes: [],
invSeqIds: [],
numChildren: 0,
addInvBtnPressed: false
};
handleAddInv = () => {
this.setState({
numChildren: this.state.numChildren + 1,
addInvBtnPressed: true
});
};
onChangeInv = (e, index, sId) => {
const invIdsArry = this.state.invIds;
const invSeqIdsArry = this.state.invSeqIds;
const newId = [
...invIdsArry.slice(0, index),
(invIdsArry[index] = e.target.value),
...invIdsArry.slice(index + 1)
];
if (sId) {
const newSeqId = [
...invSeqIdsArry.slice(0, index),
(invSeqIdsArry[index] = sId),
...invSeqIdsArry.slice(index + 1)
];
this.setState({ invIds: newId, invSeqIds: newSeqId });
} else {
this.setState({ invIds: newId });
}
};
onChangeType = (e, index) => {
const invTypesArry = this.state.invTypes;
const newTypes = [
...invTypesArry.slice(0, index),
(invTypesArry[index] = e.target.value),
...invTypesArry.slice(index + 1)
];
this.setState({ invTypes: newTypes });
};
render() {
const children = [];
var i;
if (this.state.identInvsData && !this.state.addInvBtnPressed) {
for (i = 0; i < this.state.numChildren; i += 1) {
children.push(
<Inv
key={i}
invKey={i}
onChangeInv={this.onChangeInv.bind(this)}
onChangeType={this.onChangeType.bind(this)}
invId={this.state.identInvsData[i].invId}
invType={this.state.identInvsData[i].invTypeCd}
seqId={this.state.identInvsData[i].seqId}
invData={this.state.identInvsData[i]}
/>
);
}
} else if (this.state.identInvsData && this.state.addInvBtnPressed) {
for (i = 0; i < this.state.numChildren; i += 1) {
children.push(
<Inv
key={i}
invKey={i}
onChangeInv={this.onChangeInv.bind(this)}
onChangeType={this.onChangeType.bind(this)}
/>
);
}
} else {
for (i = 0; i < this.state.numChildren; i += 1) {
children.push(
<Inv
key={i}
invKey={i}
onChangeInv={this.onChangeInv.bind(this)}
onChangeType={this.onChangeType.bind(this)}
/>
);
}
}
return (
<div>
<button
type="button"
className="btn btn-info"
onClick={this.handleAddInv}
>
Add Inv
</button>
<div>{children}</div>
</div>
)
}
}
export default Identity;
Inv Child Component Inv子组件
class Inv extends React.Component {
state = {
kddLookupData: "",
invData: ""
};
componentDidMount = () => {
kddlookups_getAll().then(resp => {
this.setState({
kddLookupData: resp.data.item
});
});
invs_getAll().then(resp => {
this.setState({
invData: resp.data.items
});
});
};
handleInvestigatorChange = e => {
this.props.onChangeInv(e, this.props.invKey, this.props.seqId);
};
handleInvestigatorTypeChange = e => {
this.props.onChangeType(e, this.props.invKey);
};
render() {
return (
<div>
<select
value={this.props.invId}
name={this.props.invKey}
onChange={this.handleInvChange.bind(this)}
>
<option className="blank">Select inv name:</option>
{this.state.invData &&
this.state.invData.map(inv => {
return (
<option key={inv.userId} value={inv.userId}>
{inv.invName}
</option>
);
})}
</select>
<select
value={this.props.invType}
name={this.props.invKey}
onChange={this.handleInvTypeChange.bind(this)}
>
<option className="blank">Select inv type:</option>
{this.state.kddData &&
this.state.kddData.kdd_inv_type.map(inv => {
return (
<option key={inv.inv_type_cd} value={inv.inv_type_cd}>
{inv.inv_type_name}
</option>
);
})}
</select>
</div>
)
}
}
export default Inv;
It doesn't look like you are returning anything in your render function in the child component. 看起来您没有在子组件的render函数中返回任何内容。 Try:
尝试:
render() {
return (
<div>
<select
value={this.props.invId}
name={this.props.invKey}
onChange={this.handleInvChange.bind(this)}
>
<option className="blank">Select inv name:</option>
{this.state.invData &&
this.state.invData.map(inv => {
return (
<option key={inv.userId} value={inv.userId}>
{inv.invName}
</option>
);
})}
</select>
<select
value={this.props.invType}
name={this.props.invKey}
onChange={this.handleInvTypeChange.bind(this)}
>
<option className="blank">Select inv type:</option>
{this.state.kddData &&
this.state.kddData.kdd_inv_type.map(inv => {
return (
<option key={inv.inv_type_cd} value={inv.inv_type_cd}>
{inv.inv_type_name}
</option>
);
})}
</select>
</div>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.