【问题标题】:Set state based on an a property present in array of objects : React+Typescript根据对象数组中存在的 a 属性设置状态:React+Typescript
【发布时间】:2019-11-07 17:19:30
【问题描述】:

我想根据对象数组中存在的属性在反应中设置状态。

看起来相似的代码沙盒:https://codesandbox.io/s/sleepy-lamarr-0sbdz

这个提交函数在 SelectComponent.tsx 中以 submitSelection() 的形式出现,我在控制台记录了问题中的状态。是一样的

我有一个看起来像这样的状态对象:

this state = {
               columns : [
                          {Header: ƒ, accessor: "firstName",show: true},
                          {Header: ƒ, accessor: "status", show: true},
                          {Header: ƒ, accessor: "visits", show: true}
                         ]
             }

我有显示列名的复选框列表,并根据“显示”标志隐藏/显示它们。 我根据复选框选择创建了一个对象数组,看起来像:

this.state = { 
              selectedOptions: [
                                {name: "firstName", value: "firstName", show: true},
                                {name: "status", value: "status", show: false},
                                {name: "visits", value: "visits", show: true}
                                ]
            } 

现在我需要根据“selectedOptions”的值来设置“columns”的状态。我必须遍历“selectedOptions”数组,然后根据每个对象的“value”(这里我用它作为键),我需要更新“columns”中对象的相应“show”属性。

在这个例子中,columns 数组应该像 setstate 之后的样子:


columns : [
            {Header: ƒ, accessor: "firstName",show: true},
            {Header: ƒ, accessor: "status", show: false}, // because the value for this in selectedOptions is true
            {Header: ƒ, accessor: "visits", show: true}
          ]


我使用了下面的方法,但是没有用


checkboxSubmit = () => {
   let { selectedOptions , columns } = this.state;
    const updatedObj = columns.map(object =>
      value.some(columns => columns.value === object.accessor)
        ? { ...object, show: columns.show  }
        : { ...object }
    );
    this.setState(columns: updatedObj);
}

【问题讨论】:

    标签: javascript reactjs typescript ecmascript-6 setstate


    【解决方案1】:

    我会从 selectedOptions 制作地图 let selectedOptionsMap = new Map(selectedOptions.map(option => [option.value, option]))

    然后将您的函数更新为:

    checkboxSubmit = () => {
       let { selectedOptions , columns } = this.state;
       let selectedOptionsMap = new Map(selectedOptions.map(option => [option.value, option]))
        const updatedColumns = columns.map(column => (
          {...column, show: selectedOptionsMap.get(column.accessor) ? selectedOptionsMap.get(column.accessor).show : column.show}
        ))
        this.setState(columns: updatedColumns)
    }
    

    如果您需要地图进行其他计算,您可以将其添加到状态中。

    ETA:根据您的代码沙箱,这里是该函数的代码

      submitSelection = () => {
        let showMap = new Map(this.state.optionsArr.map(option => [option.value, option.show]))
        let updatedColumns = this.props.data.map(column => (
          {...column, show: showMap.get(column.accessor) != null ? showMap.get(column.accessor) : column.show }
        ))
        this.props.handleSetState(updatedColumns)
      };
    

    【讨论】:

    • 这不起作用。 codesandbox.io/s/sleepy-lamarr-0sbdz 。这是沙盒的链接。这个提交函数在 SelectComponent.tsx 中以 submitSelection() 的形式出现,我在控制台记录了问题中的状态。是一样的
    • @vrosario 我已经更新了我的答案以包含您的代码沙箱中的代码
    • 您需要将其保存在状态以在渲染过程中保留它
    【解决方案2】:

    这是我的solution

    我没有在 SelectComponent 中使用 CheckBox 数据结构数组,而是使用了映射的布尔数组(仅用于显示值)——这只是我的偏好。

    我认为您之前的问题是因为您将相同的 Array 实例传递给 submitSelection。 React 不明白 App 应该更新,因为只是改变了 Array 里面的对象,而不是实际的 Array。

    您可以通过在提交之前重新创建数组来使其工作,但在这种情况下,您将改变 SelectComponent 中 App.columns 的值。如您所知,道具不应该被修改,所以这很糟糕。

    【讨论】:

    • 非常感谢@Niilo。有没有不改变道具的方法?这真的很有帮助:)
    • 在我的解决方案中,我使用 Object.assign 创建道具的副本。这行得通,但应该注意的是,道具的属性没有被深度复制,仅供参考!因此,如果其中一个属性是对象,例如 { something: number },并且您在复制的对象中修改此对象属性,它将延续到原始对象。在某些情况下,这可能是个问题,但您的数据结构似乎不包含任何非原始类型,所以应该没问题。
    • 初始化状态与构造函数相同:this.setState({ optionsArr: this.props.data.map(option => option.show) });
    【解决方案3】:

    我认为您在映射时可能混淆了变量。试试这个。

    checkboxSubmit = () => {
      this.setState(({columns, selectedOptions}) => {
        const result = columns.map(col => {
          const op = selectedOptions.find(op => col.accessor === op.value);
          return { ...col, show: op.show }
        });
        return result;
      });
    });
    

    【讨论】:

    • 这不起作用。 codesandbox.io/s/sleepy-lamarr-0sbdz 。这是沙盒的链接。这个提交函数在 SelectComponent.tsx 中以 submitSelection() 的形式出现,我在控制台记录了问题中的状态。是一样的
    猜你喜欢
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    相关资源
    最近更新 更多