Обновить вложенное состояние в реакции

Привет, ребята, я пытаюсь обновить состояние вложенного объекта в React, сейчас я делаю это:

handleChangeEvent({target: {id, value}}, type) {
    this.setState(
        state => ({
            dwelling: (Object.assign(state.dwelling, {[id]: {[type]: value}}))
        })
    );
}

это происходит из группы форм:

<FormGroup controlId = "spaces">
    <ControlLabel>Dormitorios</ControlLabel>
    <FormControl
        componentClass = "select"
        value = {dwelling.spaces.dorms}
        placeholder = "Seleccione"
        onChange = {e => this.handleChangeEvent(e, 'dorms')}
    >

Проблема в том, что когда я обновляю состояние подобъекта, создается dwelling.spaces.dorms, но когда я пытаюсь разместить другое свойство, оно заменяет старое, а не добавляется:

До Dwelling:

{
   address: "",
   currency: "",
   price: 0,
   publicationType: "",
   spaces: {
     closets: "",
     dorms: "",
     pools: ""
   },
   subtype: "",
   type: ""
}

После onChange для dwelling.spaces.dorms

{
   address: "",
   currency: "",
   price: 0,
   publicationType: "",
   spaces: {
     dorms: "3",
   },
   subtype: "",
   type: ""
}

После onChange для dwelling.spaces.closets

{
   address: "",
   currency: "",
   price: 0,
   publicationType: "",
   spaces: {
     closets: "3",
   },
   subtype: "",
   type: ""
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
3 819
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В этом примере для сохранения ваших старых свойств используется оператор распространения ES6, который является эквивалентом Object.assign.

Итак, вы не сохраняете вложенное значение.

this.setState({
  dwelling: {
    ...this.state.dwelling,
    [id]: { 
      ...this.state.dwelling[id],
      [type]: value
    }  
  }
});

В вашем примере вы заменили свое значение новым объектом. Обратите внимание на выделенный жирным шрифтом текст ниже.

dwelling: (Object.assign(state.dwelling, {[id]: {[type]: value}}))

В тексте, выделенном жирным шрифтом, он специально устанавливает новый объект в state.dwelling без сохранения старых значений. Итак, что мы сделали, так это то, что мы использовали оператор распространения ES6, чтобы помочь объединить ваши старые значения с новым значением.

{ 
  ...this.state.dwelling[id],
  [type]: value
} 

Я работал отлично, я добавил state =>, чтобы он оставался работоспособным. что происходило на последнем?

Nicolas Albarracin 18.04.2018 19:45

Что случилось, вам нужно также использовать Object.assign во вложенном значении Object.assign(state.dwelling, {[id]: Object.assign(state.dwelling[id], {[type]: value}) })

Kenneth Truong 18.04.2018 19:48

Вы перезаписывали свой [id] новым значением, и ваше новое значение никогда не получало старые реквизиты, поэтому вам нужно было использовать либо распространение, либо Object.assign во вложенном значении

Kenneth Truong 18.04.2018 19:49

не могли бы вы объяснить, что сделал ваш код, чтобы явить ваше решение, пожалуйста

Webwoman 31.01.2019 18:29

спасибо за точность @KennethTruong, если я хорошо понимаю, в первой последовательности в вашем первом примере, в setState, dwelling: { ...this.state.dwelling, [id] эквивалентен this.state.dwelling.id

Webwoman 31.01.2019 19:30

О нет! Если вы прочитали о распространении ES6, оператор ...this.state.dwelling скопирует за вас весь объект. При этом все находящиеся за ним свойства будут объединены. Итак, {...this.state.dwelling } - это то же самое, что и жилье. (За исключением того, что он создает новый объект)

Kenneth Truong 31.01.2019 19:45

Я сохраняю состояние формы в сложном объекте и для упрощения кода использую эту вспомогательную функцию в моей функции handleChangeEvent, на которую ссылаются TextField, Select и т. д.

export function updateObject(obj, keys, value) {
  let key = keys.shift();
  if (keys.length > 0) {
    let tmp = updateObject(obj[key], keys, value);
    return {...obj, [key]: tmp};
  } else {
    return {...obj, [key]: value};
  }
}

Пример React-redux / Material-UI

let [formState, changeFormState] = useState({});

function handleChangeEvent(event) {
  changeFormState(updateObject(formState, event.target.name.split('.'), 
event.target.value));
}

<TextField className = {classes.textfield} name='foo.bar' value= 
formstate.foo.bar || ''} onChange = {handleChangeEvent} />

Другие вопросы по теме