【问题标题】:How to update state of specific object nested in an array如何更新嵌套在数组中的特定对象的状态
【发布时间】:2018-06-03 07:10:47
【问题描述】:

我有一个对象数组。我希望我的函数 clicked() 向我的对象添加一个新参数(可见:false)。我不确定如何在不重新创建整个对象数组的情况下告诉 react 更新特定键的状态。

首先,有没有一种有效的方法来做到这一点(即使用扩展运算符)?

其次,也许我的整个结构都关闭了。我只想单击我的元素,然后让它收到一个指示它不再可见的道具。如果需要,有人可以建议一种替代方法吗?

import React, { Component } from 'react';
import { DefaultButton, CompoundButton } from 'office-ui-fabric-react/lib/Button';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import OilSite from './components/oilsite';
import './index.css';

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      mySites: [
        {
          text: "Oil Site 1",
          secondaryText:"Fracking",
          key: 3
        },
        {
          text: "Oil Site 2",
          secondaryText:"Fracking",
          key: 88
        },
        {
          text: "Oil Site 3",
          secondaryText:"Fracking",
          key: 12
        },
        {
          text: "Oil Site 4",
          secondaryText:"Fracking",
          key: 9
        }
      ],
    }
  };

  clicked = (key) => {
    // HOW DO I DO THIS?
  }

  render = () => (
    <div className="wraper">
      <div className="oilsites">
          {this.state.mySites.map((x)=>(
            <OilSite {...x} onClick={()=>this.clicked(x.key)}/>
          ))}
      </div>
    </div>
  )
};

export default App;

【问题讨论】:

  • 另外为了以后参考,在定义类方法时,不要使用箭头函数。箭头函数没有作用域,这意味着它们没有this。对任何类方法定义使用普通函数。

标签: reactjs


【解决方案1】:

像这样:

clicked = (key) => {
    this.state(prevState => {
      // find index of element
      const indexOfElement = prevState.mySites.findIndex(s => s.key === key);
      if(indexOfElement > -1) {
        // if element exists copy the array...
        const sitesCopy = [...prevState.mySites];
        // ...and update the object
        sitesCopy[indexOfElement].visible = false;
        return { mySites: sitesCopy }
      } 
      // there was no element with a given key so we don't update anything
    })
}

【讨论】:

    【解决方案2】:

    您可以使用数组的索引进行 O(1)(无需迭代)查找,从数组中获取站点,将属性添加到对象,更新数组,然后使用数组设置状态.请记住,map 有 3 个可以使用的参数(值、索引、数组)。

    更新:修正了一些错别字

    class Site
    {
      constructor(text, scdText, key, visible=true)
      {
        this.text = text;
        this.secondaryText = scdText;
        this.key = key;
        this.isVisible = visible;
      }
    }
    
    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          mySites: [
            new Site("Oil Site 1", "Fracking", 3),
            new Site("Oil Site 2", "Fracking", 88),
            new Site("Oil Site 3", "Fracking", 12),
            new Site("Oil Site 4", "Fracking", 9)
          ],
        }
        this.clicked = this.clicked.bind(this);
      };
      //Change to a normal function
      clicked(ind)
      {
      //Get the sites from state
        let stateCopy = {...this.state}
        let {mySites} = stateCopy;
        let oilSite = mySites[ind]; //Get site by index
        //Add property to site
        oilSite.isVisible = false;
        mySites[ind] = oilSite;//update array
        //Update the state
        this.setState(stateCopy);
    
      }
    
      render = () => (
        <div className="wraper">
          <div className="oilsites">
            {this.state.mySites.map((site, ind) => (
              //Add another parameter to map, index
              <OilSite {...site} onClick={() => this.clicked(ind)} />
            ))}
          </div>
        </div>
      )
    };

    【讨论】:

    • 谢谢。我觉得我想要完成的事情相当普遍。但是代码非常复杂。我的整个方法真的效率低下吗?你会如何处理这样的任务?
    • 一点也不,我会以几乎相同的方式设置它。你的数据是从哪里来的?另外,如果这解决了您的问题,请标记为解决方案。
    • 我可能会创建一个类来保存数据,更干净,更易于阅读。将更新我的代码以反映
    【解决方案3】:

    我不知道如何告诉 react 在不重新创建整个对象数组的情况下更新特定键的状态。

    react 的想法是返回一个新的状态对象,而不是改变旧的。

    来自 setstate 上的 react 文档,

    prevState 是对前一个状态的引用。它不应该直接突变。相反,应该通过基于 prevState 和 props 的输入构建一个新对象来表示更改

    您可以使用map 并返回一个新数组。

    clicked = (key) => {
        this.setState({
            mySites: this.state.mySites.map(val=>{
                 return val.key === key ? {...val, visibility: false} : val
            })
        })
      }
    

    【讨论】:

    • 如果我使用 setState((prevState)=>{......}) 并像这样处理 prevState,这与您使用 val 的方式相同吗?在这种情况下,val 与 prevState 是一样的吗?谢谢!
    猜你喜欢
    • 2018-07-04
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    • 2020-04-27
    • 2021-12-23
    • 2018-02-23
    • 2020-11-13
    相关资源
    最近更新 更多