How can I use `setState` with objects nested in an array in React JS?

With code, I can successfully use it setStateon a simple object - when I click on "Joey", the name changes to "Igor".

    class Card extends React.Component {
        myFunc = () => {this.props.change('Igor')};
        render() {
            return (
                <p onClick={this.myFunc}>{this.props.name}</p>
            )
        }
    }

    class Parent extends React.Component {
        constructor(props) {
            super(props)
            this.state = { name: "Joey" }
        }

        toggle = (newname) => {
            this.setState((prevState, props) => ({
                name: newname
            }));
        }

        render() {
            return (
                <Card change={this.toggle} name={this.state.name} />
            );
        }
    }

But with this code , which has several objects embedded in the array, setStateeither cannot change each name to "Igor" or it needs to be changed somehow.

    class Card extends React.Component {

        myFunc = () => {this.props.change('Igor')};
        render() {
            return (
                <p onClick={this.myFunc}>{this.props.name}</p>
            )
        }
    }

    class Parent extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                names: [
                    {
                        name: "Joey"
                    },
                    {
                        name: "Sally"
                    },
                    {
                        name: "Billy"
                    },
                ]
            }
        }

        toggle = (newname) => {
            this.setState((prevState, props) => ({
            // what can I put here to change the name I click on to "Igor"
            }));
        }

        render() {
            const names = this.state.names.map((name, index) => (
                <Card key={index} change={this.toggle} {...name} />
            ))

            return (
                <div>
                    {names}
                </div>
            );
        }
    }

Although I know that this is not how it works setState, I tried to access by nametransmitting indexand then writing this.state.names[index].name: newname. No surprises here, it didn’t work.

, . , .

setState , ?

+4
2

, .

:

toggle = (index, newname) => {
    this.setState((prevState, props) => ({
        // Return new array, do not mutate previous state.
        names: [
            ...prevState.names.slice(0, index),
            { name: newname },
            ...prevState.names.slice(index + 1),
        ],
    }));
}

render() {
    const names = this.state.names.map((name, index) => (
        // Need to bind the index so callback knows which item needs to be changed.
        <Card key={index} change={this.toggle.bind(this, index)} {...name} />
    ))

    return (
        <div>
            {names}
        </div>
    );
}

, .bind state . , , name newname.

+1

toggle:

toggle = (nameYouWantChanged, nameYouWantItChangedTo) => {

  this.setState({
    names: this.state.names.map(obj => 
      obj.name === nameYouWantChanged
        ? { name: nameYouWantItChangedTo }
        : obj
    )
  })

}
+1

Source: https://habr.com/ru/post/1676524/


All Articles