如何更新 React 组件的数组?

问题描述 投票:0回答:3

我发现当数组中的元素发生更改时,React不会更新组件。相反,必须克隆一个新数组并将其放置在其位置。

例如,我有一个

_suggestedPeople
数组。当点击代表这些人之一的 UI 元素时,我想通过调用
selectPerson
来注册它。

我希望 React 在执行此操作后能够更新:

selectPerson: function(personID, selected) {
    var person = _.find(_suggestedPeople, {id: personID});
    if (person) {
      person.selected = selected; 
    }
    return person;
  },

但是,我最终还是这样做了,这似乎没有必要:

selectPerson: function(personID, selected) {
    var index = _.findIndex(_suggestedPeople, {id: personID});
    var found = index !== -1;
    if (found) {
      var people = _.cloneDeep(_suggestedPeople);
      people[index].selected = selected;
      _suggestedPeople = people; 
    }
    return found;
  },

后者是更新 React 组件数组数据的正确方法吗?或者我错过了什么?

javascript arrays reactjs reactjs-flux flux
3个回答
0
投票

您似乎没有使用 React 的内置状态管理。如果这样做,两种状态更新方法之间的中间立场将会起作用。当组件的状态或属性发生变化时,它将重新渲染。

编辑:此代码已过时并且不是一个好的做法。请参阅下面更新的 jsfiddle

通过实现初始化组件状态

getInitialState: function () {

   var whereverItComesFrom = [
      {id: 1, selected: false},
      {id: 2, selected: false}
   ];

   return {
       suggestedPeople: whereverItComesFrom
   }
}

你的渲染方法由此渲染:

render: function () {
    var _this = this;
    var peeps = this.state.suggestedPeople.map(function(person, index){
        return <label key={index}><input type='checkbox' checked={person.selected} value={person.id} onChange={_this.handlePersonClick}/>{person.id}</label>;
    });

    return <div>{peeps}</div>;
},

handlePersonClick 可以是您的方法的合并:

handlePersonClick: function(e) {
    var selectedId = e.target.value;
    var checked = e.target.checked;
    var peeps = this.state.suggestedPeople;
    var index = _.findIndex(peeps, {id: selectedId});

    peeps[index].selected = checked;

    this.setState({suggestedPeople: peeps});

}

编辑:上面的内容对我来说是非常不明智的早期反应。我已经更新了下面的小提琴链接,它应该作为解决此问题的一个很好的基本示例。

完整jsfiddle


0
投票

我认为你做错了。你可能会从 Angular JS 中做出反应。要操作对象,请使用 useState,而不是使用函数。组件中的本地状态。

样品:

const Comp = () => {
  const [selectedPerson, setSelectedPerson] = useState({});
  function onSelect(personID, selected) {
    var person = _.find(_suggestedPeople, { id: personID });
    if (person) {
      person.selected = selected;
    }
    setSelectedPerson(person);
  }
  return (
    <div>
      {selectedPerson.name}
      <select>
        <option onSelect={() => onSelect(id, "ssjsjs")}></option>
      </select>
    </div>
  );
};

0
投票

React setState是浅比较,没有必要使用cloneDeep。只需将指针更改为

_suggestedPeople
的地址即可触发react重新渲染。你可以这样尝试:

const App = () => {
  const [_suggestedPeople, setSuggestedPeople] = useState([
    {
      id: '1',
      name: 'A',
      selected: false,
    },
    {
      id: '2',
      name: 'B',
      selected: false,
    },
  ])
  const handleUserClick = (personID, selected) => {
    const person = _.find(_suggestedPeople, { id: personID })
    if (person) {
      person.selected = selected
    }
    setSuggestedPeople([..._suggestedPeople])
  }

  return (
    <div>
      {_suggestedPeople.map((user) => {
        return (
          <div
            onClick={() => {
              // selected or other things
              handleUserClick(user.id, true)
            }}
            className={user.selected ? 'selected' : ''}
          >
            {user.name}
          </div>
        )
      })}
    </div>
  )
}

export default App

© www.soinside.com 2019 - 2024. All rights reserved.