【问题标题】:Correct way to setState a property of nested object with array properties使用数组属性设置嵌套对象属性的正确方法
【发布时间】:2019-04-18 22:35:31
【问题描述】:

美好的一天!我有一个带有子数组的嵌套状态,我想知道 setState 的正确和最佳方法。

这是一个示例状态对象。 已编辑,忘了说lists 是array of objects。

this.state = {
     lists:
          [{

               name: 'sampleList',
               id: 15,
               permission: {
                    canRead: true,
                    canWrite: false
               }
          }]
     }
}

我用它来设置权限属性的状态,但状态没有更新。

this.setState({
     ...this.state, lists: {
          ...this.state.lists, key: [
               ...this.state.lists.key, permission : {
                    ...this.state.lists.key.permission, 
                    canRead: !this.state.lists.key.permission.canRead
               }
          ] 
     }
 });

我希望你能帮助我。谢谢!

【问题讨论】:

  • 在 setState 中,您使用的是对象 {...this.state.list} 而不是 [...this.state.lists] 这是问题。

标签: javascript reactjs babeljs jsx


【解决方案1】:

您可以创建lists 数组的副本,然后将要更改的索引的对象替换为同一对象的副本,但您更改了permission。

示例

class App extends React.Component {
  state = {
    lists: [
      {
        name: "sampleList",
        id: 15,
        permission: {
          canRead: true,
          canWrite: false
        }
      }
    ]
  };

  updateList = (index, canRead, canWrite) => {
    this.setState(prevState => {
      const lists = [...prevState.lists];
      lists[index] = { ...lists[index], permission: { canRead, canWrite } };
      return { lists };
    });
  };

  render() {
    return (
      <div>
        <button onClick={() => this.updateList(0, false, true)}>
          Update state
        </button>
        <div>{JSON.stringify(this.state)}</div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

【讨论】:

  • 嗨@Tholle,谢谢你的回答。尽管我已经对其进行了一些更新以满足我的目标,但这对我有用。再次感谢您。
  • 我想知道,如果你不知道索引怎么办,相反,你有一个“id”。你会先使用findIndex 吗?
【解决方案2】:

使用setState更改数组的特定元素的方法是将数组的所有项原样复制,但目标项除外,这可以通过.map和if语句完成:

export default class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            lists: [
                {
                    name: 'sampleList',
                    id: 15,
                    permission: {
                        canRead: true,
                        canWrite: false
                    }
                }
            ]
        }
    }

    invertCanRead(targetId) {
        this.setState({
            ...this.state,
            lists: this.state.lists.map(list => {
                if (list.id === targetId) {
                    // that is the one we want to modify, so let's return
                    // modified version:
                    return {
                        ...list,
                        permission: {
                            ...list.permission,
                            canRead: !list.permission.canRead
                        }
                    }
                } else {
                    // else return list as is without changes because
                    // it's not the one we want to modify, so just copy it:
                    return list;
                }
            })
        })
    }

    render() {
        return <div>
            {JSON.stringify(this.state)};
            <button onClick={() => this.invertCanRead(15)}></button>
        </div>
    }
}

【讨论】:

  • 嗨@ilonacodes,第一个答案对我来说更干净。感谢您的努力,它确实给了我一些想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 2021-07-10
  • 2022-11-20
  • 2012-01-18
相关资源
最近更新 更多