【问题标题】:How can I use `setState` with objects nested in an array in React JS?在 React JS 中,如何对嵌套在数组中的对象使用`setState`?
【发布时间】:2017-05-06 02:05:29
【问题描述】:

有了这个code,我可以在一个简单的对象上成功使用setState——当我点击“Joey”时,名字会变成“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} />
            );
        }
    }

但是对于这个在数组中嵌套多个对象的codesetState 要么无法将每个名称更改为“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 = {
                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>
            );
        }
    }

尽管我知道setState 不是这样工作的,但我还是尝试通过传递index 然后写入this.state.names[index].name: newname 来访问name。这里没有意外,它没有工作。

尽管我发现很多关于不变性助手的提及,但我已经研究并找不到关于此的类似问题。但我仍然不确定这是否是要走的路。

使用setState 修改嵌套在数组中的对象的最佳方法是什么?

【问题讨论】:

  • this.setState(this.state)?
  • 如何知道点击的是哪一个?您需要一些标识符,例如特定Card 的索引。

标签: javascript reactjs setstate


【解决方案1】:

修改了你的代码,可以在here找到工作示例。

可在此处找到更改:

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

【讨论】:

  • 这很有帮助,谢谢 Tay。这很有效,但对于以后可能会看到的其他人来说——我在最初的问题中没有提到,我希望避免使用.bind(this),原因是here(参见“方式#2”)。在 Tay 的帮助下,我能够在不使用 .bind(this) 的情况下重写我的 code
【解决方案2】:

我会将它用于切换方法:

toggle = (nameYouWantChanged, nameYouWantItChangedTo) => {

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

}

【讨论】:

  • 谢谢布拉德,这很聪明。您在第 7 行缺少 ),应该在 : obj 之后,但这是一个很好的解决方案。我已经修改了我的code,以便其他人可以看到这是如何解决问题的。
  • Brad,也只是想让您知道,我选择 Tay 的解决方案而不是您的解决方案,因为他使用 index 可以防止出现问题,例如,在数组中的多个对象可能共享相同的情况下名字。
猜你喜欢
  • 1970-01-01
  • 2020-02-19
  • 1970-01-01
  • 1970-01-01
  • 2019-11-02
  • 1970-01-01
  • 2015-08-31
  • 2019-08-03
  • 1970-01-01
相关资源
最近更新 更多