[英]React setState changes child's props
因此,我的目標是擁有一個React組件,從本質上講,如果您按下按鈕,則可以讓您擁有幾個子組件。 我要管理頂級組件中的狀態,當您單擊提交時,我希望該組件的狀態本質上是一個對象數組,列表中每個組件一個元素。 我的解決方案想法是呈現幾個子組件並將其傳遞給索引。 然后,我給他們上層onChange
函數,讓他們使用索引進行調用。 這個問題是,直到我在上層onChange
函數中調用this.setState
之前,它都可以工作。 由於某種原因,調用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>
);
}
}
這可能是因為在構造函數中,您this.onChange
分配給一個functions
對象,該對象在AddressesDataForm
組件的所有實例之間共享。 第一次渲染每個實例時,僅調用了構造functions.onChange
,而functions.onChange
將具有正確的值。 但是,在設置父級的狀態並重新渲染每個實例時,不會調用任何構造functions.onChange
,並且在三個渲染中的每個functions.onChange
中的functions.onChange
都將引用第三個this.onChange
(它使用索引2調用this.props.onChange
)。
如果不運行代碼,很難看到它,但是我想僅僅使用this.onChange
就可以解決問題。 另外,為避免混淆,您可以將傳遞給AddressesDataForm
的prop重命名為onchange
以外的其他名稱。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.