Как обновить единственное свойство из массива объекта, используя setState (с компонентом класса)? - PullRequest
0 голосов
/ 14 июня 2019

У меня есть массив объектов в this.state, и я пытаюсь обновить одно свойство из массива объектов.

Это мой объект

 this.state = {
  persons: [
    { name: "name1", age: 1 },
    { name: "name2", age: 2 },
    { name: "name3", age: 3 }
  ],
  status: "Online"
};

и я попытался обновить людей [0] .name

import React, { Component } from "react";     
class App extends Component {
      constructor() {
        super();
        this.state = {
          persons: [
            { name: "John", age: 24 },
            { name: "Ram", age: 44 },
            { name: "Keerthi", age: 23 }
          ],
          status: "Online"
        };
      }
      changeName() {
        console.log(this);
        this.setState({
         persons[0].name: "sdfsd"
        });
      }

      render() {
        return (
        <button onClick={this.changeName.bind(this)}>change name</button>
        );
      }
    }

получаю ошибку.

Ответы [ 7 ]

3 голосов
/ 14 июня 2019

Вы должны код:

let persons = [...this.state.persons]
persons[0].name= "updated name"
this.setState({ persons })
0 голосов
/ 11 июля 2019

с помощью оператора точки мы можем достичь этого.

    let persons = [...this.state.persons]
persons[0].name= "updated name"
this.setState({ persons })
0 голосов
/ 14 июня 2019

Вот как бы я это сделал.

Посмотрите, работает ли это для вас.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      persons: [
        { name: "John", age: 24 },
        { name: "Ram", age: 44 },
        { name: "Keerthi", age: 23 }
      ],
      status: "Online"
    };
    this.changeName = this.changeName.bind(this);
    this.changeAge = this.changeAge.bind(this);
  }
  
  changeName(value,index) {
    this.setState((prevState)=>{
      const aux = prevState.persons;
      aux[index].name = value;
      return aux;
    });
  }
  
  changeAge(value,index) {
    this.setState((prevState)=>{
      const aux = prevState.persons;
      aux[index].age = value;
      return aux;
    });
  }
    
    render() {
      const personItems = this.state.persons.map((item,index)=>
        <React.Fragment>
          <input value={item.name} onChange={(e)=>this.changeName(e.target.value,index)}/>
          <input value={item.age} onChange={(e)=>this.changeAge(e.target.value,index)}/>
          <br/>
        </React.Fragment>
      );
      
      return(
        <React.Fragment>
          {personItems}
          <div>{JSON.stringify(this.state.persons)}</div>
        </React.Fragment>
      );
      
    }
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
0 голосов
/ 14 июня 2019

Я думаю, что лучший способ - сначала скопировать состояние во временную переменную, а затем после обновления этой переменной перейти к setState

let personsCopy = this.state.persons
personsCopy [0].name= "new name"
this.setState({ persons: personsCopy  })
0 голосов
/ 14 июня 2019

Предполагая некоторую условную проверку, чтобы найти нужного человека.

const newPersonsData = this.state.persons.map((person)=>{
    return person.name=="name1" ? person.name="new_name" : person);
                      //^^^^^^^ can be some condition
});

this.setState({...this.state,{person:[...newPersonsData ]}});
0 голосов
/ 14 июня 2019
this.setState(state => (state.persons[0].name = "updated name", state))
0 голосов
/ 14 июня 2019

Проблема в том, что вы изменяете состояние компонента, ниже приведен пример неизменяемого изменения, я рекомендую вам прочитать статьи о том, как изменить состояние реакции. Или вы можете попробовать использовать Mobx, потому что он поддерживает изменчивость

changePerson(index, field, value) {
  const { persons } = this.state;

  this.setState({
    persons: persons.map((person, i) => index === i ? person[field] = value : person)
  })
}

// and you can use this method 
this.changePerson(0, 'name', 'newName')
...