Почему перехватчик useState изменяет другой объект, не вызывая его? - PullRequest
0 голосов
/ 26 марта 2020

У меня есть компонент React, который извлекает данные при первой загрузке.


const [data, setDate] = useState(null);
const [originalData, setOriginalData] = useState(null);

useEffect(() => {
    async function fn() {
      let res = await getObject();
      setData({...res});
      setOriginalData({...res});
    }

    fn();
}, [])

Я вызываю 2 разных хука для установки состояний data и originalData.

Цель это значит, что у меня есть неизменная версия данных, к которой я могу обратиться для некоторых из logi c в компоненте.

Однако, когда я изменяю состояние data, кажется, что также меняю состояние originalData, и я ничего не буду вызывать.

const change() => {
    let updatedData = {...data};
    updatedData.someProperty = 'newValue';
    setData(updatedData);
}

Я бы ожидал, что данные теперь содержат свойство someProperty со значением newValue, и что originalData будет быть неизменным от начальной нагрузки.

Но когда я сравниваю их, data и originalData оба теперь имеют someProperty.

Может ли кто-нибудь указать мне правильное направление?

РЕДАКТИРОВАТЬ: добавить оператор распространения

1 Ответ

0 голосов
/ 26 марта 2020

Проблема: та же ссылка

Причина, по которой изменение data меняет originalData, не из-за перехватов React, а из-за поведения объектов в JavaScript. Хотя data и originalData различны, они все еще ссылаются на один и тот же объект (из res). Таким образом, любые изменения, внесенные в один из них, будут отражены в другом, поскольку они имеют одинаковые ссылки.

Решение: клон

По этой причине вам следует клонировать данные вместо непосредственного их назначения.

// JSON 
const originalData = JSON.parse(JSON.stringify(res))

// Object.assign
const originalData = Object.assign({}, res)

// Or spread opr
const originalData = { ...res }

// Then set the state
setOriginalData(originalData);

Методы ES6, такие как Object.assign и оператор распространения, делают поверхностную копию. Если вам нужна глубокая копия и если ваши данные не имеют дат, функций, неопределенных, Infinity, RegExps, карт, наборов, BLOB-объектов, списков файлов, ImageDatas, разреженных массивов, типизированных массивов или других сложных типов в вашем объекте, go для JSON разбора, stringify.

Проверьте этот вопрос для получения дополнительной информации о клонировании в JavaScript

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