简体   繁体   中英

Set state on specific component in React

I have many of the same component render on one page, my user can add more of the same child components if they want. When they choose the date within the form element of the child component I only want to change the date of the child component they selected. At the moment it changes the date for all the child components on the screen, can anyone see where I am going wrong?

class ParentFixturesComponent extends Component {

    constructor() {
        super();
        this.state = {
            numChildren: 0,
            startDate: moment(),
            id: uuid()
        };
    }

    changeDate(newDate) {
        this.setState({
            startDate: newDate
        });
    }

    onAddMatch() {
        this.setState({
            numChildren: this.state.numChildren + 1
        });
    }

    render() {
        const children = [];
        for (let i = 0; i < this.state.numChildren; i += 1) {
            children.push(<SingleMatchForm startDate={this.state.startDate}
                                           key={this.state.id}
                                           changeDate={this.changeDate.bind(this)}
            />)
        }

        return (
            <Fixtures addMatch={this.onAddMatch.bind(this)}>
                {children}
            </Fixtures>
        );
    }

}

export default ParentFixturesComponent;

Child component

class SingleMatchForm extends Component {

    handleChange(params) {
        this.props.changeDate(params);
    }

    render() {
        return (
            <div className="row">
                <div key={this.props.id} className="form-group">
                    <label className="control-label col-md-2">New Match</label>
                    <div className="col-md-6">
                        <DatePicker
                            selected={this.props.startDate}
                            onChange={this.handleChange.bind(this)}/>
                        <div className="section-divider mb40" id="spy1"> </div>
                    </div>
                </div>
            </div>
        );
    }

}

export default SingleMatchForm;

Reason is, you are using single state variable to save the date value of all the child components, if you update that single state value it will affect all the components. To solve this problem use an array instead of single value.

Like this:

this.state = {
    numChildren: 0,
    startDate: [],  //array
    id: uuid()
};

Now use each value of this array for each child component and bind the index in onChange method to update the specific value, like this:

children.push(<SingleMatchForm startDate={this.state.startDate[i] || moment()}
                                           key={this.state.id}
                                           changeDate={this.changeDate.bind(this, i)}
            />)

And inside onChange method update the specific value not all the value:

changeDate(i, newDate) {
    let startDate = this.state.startDate.slice();
    startDate[i] = newDate;
    this.setState({
        startDate
    });
}

I only want to change the date of the child component they selected.

Then the child Component should hold date as its state, or Make the parent hold the dates in an array from all the child components.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM