所以我的目标是让一个反应组件,如果按一个按钮,基本上可以让你拥有一些子组件。我想管理顶级组件中的状态,当你点击提交时,我希望这个组件的状态基本上是一个对象数组,列表中每个组件的一个元素。我对解决方案的想法是渲染一些子组件并向它们传递索引。然后,我给他们上层onChange
函数,让他们用索引调用。这个问题是它在我在上层this.setState
函数中调用onChange
之前一直有效。出于某种原因,调用this.setState
会导致我的index
参数始终是子元素列表中的最高数字索引。
这是AddressesDataForm.js:
export default class AddressesDataForm extends React.Component {
constructor(props) {
super(props);
if (this.props.onChange) {
functions.onChange = this.onChange;
}
if(this.props.onSubmit) {
functions.onSubmit = this.props.onSubmit;
}
this.state = {
'tableName': 'Addresses',
states: [
'Gotta',
'Hook',
'Into',
'State',
'Api',
'Still'
],
county_disabled: true,
counties: {
'Gotta': ['a', 'b', 'c'],
'Hook': ['d', 'e', 'f'],
'Into': ['e', 't', 'c'],
'State': ['e', 't', 'c'],
'Api': ['e', 't', 'c'],
'Still': ['e', 't', 'c']
},
use_counties: [],
countries: [
'United States of America',
'Elsewhere'
],
index: this.props.index
}
console.log(this.props.index);
}
onChange = (name, value) => {
if (name == 'state') {
if (value.length > 0) {
this.setState({
county_disabled: false,
use_counties: this.state.counties[value]
});
} else {
this.setState({
county_disabled: true
});
}
}
console.log(this.props.index); //notice this.props.index, tried this.state as well and it didn't work either
this.props.onChange(name, value, this.props.index);
}
render() {
return (
<DataForm tableName={this.state.tableName} onSubmit={functions.onSubmit.bind(this)} {...this.props}>
<SelectField
menuItems={['Home', 'Work', 'Other']}
defaultValue="Home"
className='md-cell md-cell--2 md-cell--middle'
onChange={functions.onChange.bind(this, "address_type_select")}
/>
<TextField
label="Street Address Line 1"
maxLength={128}
className='md-cell md-cell--10'
onChange={functions.onChange.bind(this, "address_line_1")}
/>
<TextField
label="Street Address Line 2"
maxLength={128}
className='md-cell md-cell--2-desktop-offset md-cell--10'
onChange={functions.onChange.bind(this, "address_line_2")}
/>
<TextField
label="City"
maxLength={64}
className='md-cell md-cell--2-desktop-offset md-cell--5'
onChange={functions.onChange.bind(this, "city")}
/>
<SelectField
label="State"
maxLength={64}
className='md-cell md-cell--2'
menuItems={this.state.states}
onChange={this.onChange.bind(this, "state")}
/>
<TextField
label="ZIP code"
className='md-cell md-cell--3'
onChange={functions.onChange.bind(this, "zip_code")}
required
/>
<SelectField
label="Country"
className='md-cell md-cell--2-desktop-offset md-cell--10'
menuItems={this.state.countries}
defaultValue={this.state.countries[0]}
onChange={functions.onChange.bind(this, "country")}
/>
<h6 className="md-cell md-cell--2-desktop-offset md-cell--10">Location Information</h6>
<SelectField
label="County"
className='md-cell md-cell--2-desktop-offset md-cell--10'
menuItems={this.state.use_counties}
onChange={this.onChange.bind(this, "county")}
helpText={this.state.county_disabled ? 'Select a state' : ''}
disabled={this.state.county_disabled}
/>
<SelectionControl
id={"switch-primary-address" + this.props.index}
className='md-cell md-cell--12 md-cell--2-desktop-offset'
type="switch"
label="Primary address"
onChange={functions.onChange.bind(this, "primary_address")}
checked={this.props.isPrimary}
/>
{this.props.noAddButton ?
null :
<div className="md-cell">
<Button
style={{ display: "inline-block" }}
floating mini secondary
onClick={this.props.onAddClicked}>
add circle
</Button>
<p style={{ display: "inline-block", margin: "10px" }}>Add address</p>
</div>}
{this.props.noButton ? null : <h6 className="md-cell md-cell--12">* Required Fields</h6>}
<p>{this.props.index}</p>
</DataForm>
);
}
}
和AddressesDeck.js
export default class AddressesDeck extends React.Component {
constructor(props) {
super(props);
this.state = {
addresses: 3,
primaryAddress: 0,
data: {}
};
}
onAddClicked = () => {
this.setState({
addresses: this.state.addresses + 1,
primaryAddress: this.state.addresses
});
}
onChange = (name, value, index) => {
console.log(index); //properly logs the index
// this.setState(prevState => ({ //unless this is un-commented, then it always logs 2
// 'something unrelated':value
// }));
console.log(this.state);
// if (name == 'primary_address') {
// this.setState({
// primaryAddress: index
// });
// }
}
render() {
return (
// <div>
// {[...new Array(this.state.addresses)].map((_, i) => (
// <Paper id="main" key={i}>
// <AddressesDataForm
// onChange={this.onChange.bind(this, i)}
// onSubmit={functions.onSubmit.bind(this)}
// key={i}
// index={i}
// onAddClicked={this.onAddClicked.bind(this)}
// noButton={i != this.state.addresses - 1}
// noAddButton={i != this.state.addresses - 1 || this.state.addresses == 3}
// noTitle={i != 0}
// isPrimary={this.state.primaryAddress == i} />
// </Paper>
// ))}
// </div>
<div>
<Paper id="main" key={0}>
<AddressesDataForm
onChange={this.onChange}
onSubmit={functions.onSubmit.bind(this)}
key={0}
index={0}
onAddClicked={this.onAddClicked.bind(this)}
noButton={0 != this.state.addresses - 1}
noAddButton={0 != this.state.addresses - 1 || this.state.addresses == 3}
noTitle={0 != 0}
isPrimary={this.state.primaryAddress == 0} />
</Paper>
<Paper id="main" key={1}>
<AddressesDataForm
onChange={this.onChange}
onSubmit={functions.onSubmit.bind(this)}
key={1}
index={1}
onAddClicked={this.onAddClicked.bind(this)}
noButton={1 != this.state.addresses - 1}
noAddButton={1 != this.state.addresses - 1 || this.state.addresses == 3}
noTitle={1 != 0}
isPrimary={this.state.primaryAddress == 1} />
</Paper>
<Paper id="main" key={2}>
<AddressesDataForm
onChange={this.onChange}
onSubmit={functions.onSubmit.bind(this)}
key={2}
index={2}
onAddClicked={this.onAddClicked.bind(this)}
noButton={2 != this.state.addresses - 1}
noAddButton={2 != this.state.addresses - 1 || this.state.addresses == 3}
noTitle={2 != 0}
isPrimary={this.state.primaryAddress == 2} />
</Paper>
</div>
);
}
}
答案 0 :(得分:1)
这可能是因为在构造函数中,您将this.onChange
分配给functions
对象,该对象在AddressesDataForm
组件的所有实例之间共享。第一次渲染每个实例时,刚刚调用了构造函数,functions.onChange
将具有正确的值。但是,在设置父级状态并重新渲染每个实例时,不会调用构造函数,并且三个渲染中的每个渲染中的functions.onChange
将引用第三个this.onChange
(使用索引调用this.props.onChange
2。)
在没有运行代码的情况下有点难以看到,但我想只需使用this.onChange
即可解决问题。另外,为防止混淆,您可以将传递给AddressesDataForm
的道具重命名为onchange
以外的其他内容。