簡體   English   中英

反應setState改變孩子的道具

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM