Значения в состоянии объекта React изменяются странным образом - PullRequest
0 голосов
/ 05 октября 2019

Я новичок в React и пытаюсь узнать, когда на объект состояния влияет, когда я копирую объект в нем.

В следующем коде;Первый сценарий вызывает обновление объекта состояния, а второй - НЕ. Мне нужно знать, в чем разница и почему это происходит?

import React, { Component } from "react";

export class Test extends Component {
  state = {
    counters: [
      { id: 1, desc: "Item1 default description" },
      { id: 2, desc: "Item2 default description" }
    ]
  };
  handleAction() {
    const counters = { ...this.state.counters };

    ////First Scenario
    console.log("Item description before updating:", counters[0].desc);
    counters[0].desc = "Item1 description updated successfully!"; //<--This line makes the state updated
    console.log("Item description after updating:", counters[0].desc);
    console.log(
      "Item description value in state object:",
      this.state.counters[0].desc //Item value is updated in the state object.
    );

    ////Second Scenario

    // console.log("Item description before updating:", counters[0].desc);
    // counters[0] = { id: 1, desc: "Item1 description updated successfully!" }; //<--This line does NOT affect the state
    // console.log("Item description after updating:", counters[0].desc);
    // console.log(
    //   "Item description value in the state object:", //Item value is NOT updated in the state object.
    //   this.state.counters[0].desc
    // );
  }

  render() {
    return (
      <React.Fragment>
        {this.state.counters[0].desc}
        <button
          className="btn btn-danger btn-sm"
          onClick={() => this.handleAction()}
        >
          Check Item description in state object
        </button>
      </React.Fragment>
    );
  }
}

Ответы [ 3 ]

2 голосов
/ 05 октября 2019

В JS объекты передаются по ссылке . И следующий синтаксис копирует массив, но не копирует хранящиеся в нем объекты. Это называется мелкой копией.

const counters = { ...this.state.counters };

В первом случае вы обновляете ссылку на объект, на который также ссылается переменная state.

Но когда выназначая элемент массива, вы создаете новый объект, о котором state не знает, поэтому он не изменен.

0 голосов
/ 05 октября 2019

Оператор распространения { ...obj } делает поверхностное копирование, что означает, что в данном случае он только дублирует структуру массива счетчиков, а не содержимое каждого элемента.

Значение адресов или ссылки counter[0] иcounter[1] дублируются, а не объекты, которые они держат. Таким образом, обновление counter[0].desc также обновит свойство desc в исходном объекте состояния.

Но обновление counter[0] только обновляет дубликат и не влияет на оригинальную копию в объекте состояния.

Проверьте этот пост , чтобы лучше понять мелкую иглубокая копия.

Я также должен добавить, что вы всегда должны обновлять состояние реакции, используя this.setState, чтобы избежать неожиданных результатов.

Наконец, некоторые люди будут спорить об использовании вложенных свойств, потому что Reactне ориентирован на работу с вложенным состоянием. Может быть, это правильно или нет, но вот что я думаю:

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

0 голосов
/ 05 октября 2019

Вам необходимо обновить состояние, используя setState. Непосредственное изменение состояния - это то, что вы не должны делать: https://reactjs.org/docs/state-and-lifecycle.html#do-not-modify-state-directly

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...