Обновление объекта с помощью setState в React

103

Возможно ли вообще обновить свойства объекта с помощью setState?

Что-то вроде:

this.state = {
   jasper: { name: 'jasper', age: 28 },
}

Я пробовал:

this.setState({jasper.name : 'someOtherName'});

и это:

this.setState({jasper:{name:'someothername'}})

Первая - это синтаксическая ошибка, а вторая ничего не делает. Любые идеи?

  • 3
    второй код сработал бы, однако вы потеряли бы свойство age внутри jasper .
Теги:
state

10 ответов

227
Лучший ответ

Существует несколько способов сделать это.

1- Самый простой:

Сначала создайте копию jasper, затем выполните изменения в этом:

let jasper = Object.assign({}, this.state.jasper);    //creating copy of object
jasper.name = 'someothername';                        //updating value
this.setState({jasper});

Вместо использования Object.assign мы также можем записать его следующим образом:

let jasper = {...this.state.jasper};

2- Используя оператор распространения:

this.setState(prevState => ({
    jasper: {
        ...prevState.jasper,
        name: 'something'
    }
}))
  • 0
    То, как я пытался сейчас, работает, хотя ... второй путь: S
  • 6
    @JohnSnow в вас второй будет удалить другие свойства из jasper объекта, сделать console.log(jasper) вы увидите только одно ключевое name , возраст не будет там :)
Показать ещё 10 комментариев
11

Самый быстрый и самый читаемый способ:

this.setState({...this.state.jasper, name: 'someothername'});

Несмотря на то, что this.state.jasper уже содержит свойство name, следует использовать последнее name: 'someothername'.

  • 13
    Это решение имеет один большой недостаток: для оптимизации обновлений состояния React может группировать несколько обновлений. Как следствие, this.state.jasper не обязательно содержит последнее состояние. Лучше использовать обозначения с prevState .
6

Используйте оператор распространения и немного ES6 здесь

this.setState({
    jasper: {
          ...this.state.jasper,
          name: 'something'
    }
})
5

Я использовал это решение.

Если у вас есть вложенное состояние, подобное этому:

   this.state = {
          formInputs:{
            friendName:{
              value:'',
              isValid:false,
              errorMsg:''
            },
            friendEmail:{
              value:'',
              isValid:false,
              errorMsg:''
            }
}

Вы можете объявить функцию handleChange, которая копирует текущее состояние и переназначает его с измененными значениями.

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let statusCopy = Object.assign({}, this.state);
    statusCopy.formInputs[inputName].value = inputValue;

    this.setState(statusCopy);
  }

здесь HTML с прослушивателем событий. Убедитесь, что вы используете то же имя, что и для объекта состояния (в данном случае "friendName")

<input type="text" onChange={this.handleChange} " name="friendName" />
3

Первый случай - действительно синтаксическая ошибка.

Так как я не вижу остальных компонентов, трудно понять, почему вы размещаете объекты в своем состоянии здесь. Неплохо встраивать объекты в состояние компонента. Попробуйте установить начальное состояние:

this.state = {
  name: 'jasper',
  age: 28
}

Таким образом, если вы хотите обновить имя, вы можете просто вызвать:

this.setState({
  name: 'Sean'
});

Достигнет ли это того, к чему вы стремитесь?

Для больших, более сложных хранилищ данных я бы использовал что-то вроде Redux. Но это гораздо более продвинутый.

Общее правило с состоянием компонента - использовать его только для управления состоянием пользовательского интерфейса компонента (например, активным, таймерам и т.д.).

Проверьте эти ссылки:

  • 1
    Я использовал это только в качестве примера, объект должен быть вложенным ... Я, вероятно, должен использовать Redux, но я пытаюсь понять основы React ...
1

попробуйте это, оно должно работать нормально

this.setState(Object.assign(this.state.jasper,{name:'someOtherName'}));
  • 0
    Я пробовал много других методов ... но твой фрагмент - рок! Спасибо чувак
  • 0
    Большое спасибо за то, что дали мне знать. Я счастлив, что решил твою проблему.
0

Вы можете попробовать это: (Примечание: имя входного тега === поле объекта)

<input name="myField" type="text" 
      value={this.state.myObject.myField} 
     onChange={this.handleChangeInpForm}></input>

-----------------------------------------------------------
handleChangeInpForm = (e) => {
   let newObject = this.state.myObject;
   newObject[e.target.name] = e.target.value;
   this.setState({
     myObject: newObject 
   })
}
  • 0
    Добро пожаловать в стек переполнения. Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, повышает его долгосрочную ценность. Как ответить
0

Вы можете попробовать это:

this.setState(prevState => {
   prevState = JSON.parse(JSON.stringify(this.state.jasper));
   prevState.name = 'someOtherName';
   return {jasper: prevState}
})

или для другого имущества:

this.setState(prevState => {
   prevState = JSON.parse(JSON.stringify(this.state.jasper));
   prevState.age = 'someOtherAge';
   return {jasper: prevState}
})

Или вы можете использовать функцию handleChage:

handleChage(event) {
   const {name, value} = event.target;
    this.setState(prevState => {
       prevState = JSON.parse(JSON.stringify(this.state.jasper));
       prevState[name] = value;
       return {jasper: prevState}
    })
}

и HTML-код:

<input 
   type={"text"} 
   name={"name"} 
   value={this.state.jasper.name} 
   onChange={this.handleChange}
/>
<br/>
<input 
   type={"text"} 
   name={"age"} 
   value={this.state.jasper.age} 
   onChange={this.handleChange}
/>
0

Также, следуя решению Альберто Пираса, если вы не хотите копировать весь объект "состояние":

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let jasperCopy = Object.assign({}, this.state.jasper);
    jasperCopy[inputName].name = inputValue;

    this.setState({jasper: jasperCopy});
  }
0

Другой вариант: определить вашу переменную из объекта Jasper, а затем просто вызвать переменную.

Оператор спреда: ES6

this.state = {  jasper: { name: 'jasper', age: 28 } } 

let foo = "something that needs to be saved into state" 

this.setState(prevState => ({
    jasper: {
        ...jasper.entity,
        foo
    }
})
  • 1
    Я не уверен, что downvoter (s) понял, что foo расширяется до foo: foo ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню