Журнал консоли до того, как setState напечатает сообщение об обновлении

У меня есть функция обратного вызова из объекта таблицы, где я отлаживал некоторые данные и хотел выполнить console.log объекта таблицы до того, как он был обновлен с помощью this.setState(). Теперь я знаю, что this.setState является асинхронным, но я все еще ожидал увидеть журнал перед обновлением, но вместо этого он появился после обновления.

Вот функция обратного вызова:

onCellChange = (tableId, rowIdx, cellIdx) => e => {
    const value = parseFloat(e.target.value);
    console.log("TableID:", tableId);
    console.log(tableData); //This prints the tableData object post-this.setState()
    const tableTuple = { rowIdx, cellIdx, value, tableData, tableId };

    this.setState({
      tableData: updateInput(tableTuple)
    });
};

Чтобы проверить это, я закомментировал вызов this.setState и повторил попытку, и console.log() напечатал значение до обновления, как и ожидалось, поскольку оно больше не входит в метод updateInput. Это имеет смысл, но тогда я не уверен, как получить значение console.log перед обновлением.


person Javia1492    schedule 21.11.2019    source источник
comment
updateInput вероятно мутирует Объект. Консоль ссылается на объект и отражает любые изменения, которые он получает.   -  person Emile Bergeron    schedule 21.11.2019
comment
Подвести итог; 1. Не изменяйте состояние в функции updateInput и 2. Консоль регистрирует json вместо объекта: console.log(JSON.stringify(tableData))   -  person HMR    schedule 21.11.2019
comment
Я не вижу, когда установлено значение объекта tableData. Разве вы не должны вместо этого писать console.log(this.state.tableData)?   -  person Sylvain    schedule 21.11.2019
comment
@EmileBergeron Хорошо, передача объекта состояния в качестве параметра по-прежнему изменит исходное состояние? Я предполагал, что он изменит только сам параметр, а не оригинал. В противном случае без this.setState я бы увидел отраженные изменения, однако, когда я его комментирую, я не вижу обновления состояния.   -  person Javia1492    schedule 21.11.2019
comment
@Javia1492 объекты в JS ссылаются только на переменные, поэтому параметр является просто ссылкой на тот же объект состояния.   -  person Emile Bergeron    schedule 21.11.2019


Ответы (1)


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

Из-за этого ваша консоль показывает вам состояние tableData после того, как оно было изменено. (Спасибо Эмилю Бержерону за разъяснения).

Вы можете избежать этого, зарегистрировав клон вашего объекта, например:

const tableDataCopy = { ...tableData };
console.log(tableDataCopy);

Или, если вы не можете использовать ES6 или вам нужна настоящая глубокая копия, вы можете сделать

const tableDataCopy = JSON.parse(JSON.stringify(tableData));
console.log(tableDataCopy);
person Michael Horn    schedule 21.11.2019
comment
Это не медленно, в интерфейсе консоли даже объясняется, что объект оценивается при расширении. - person Emile Bergeron; 21.11.2019
comment
Интересно... Итак, если я правильно вас понимаю, вывод консоли в chrome может измениться после того, как он уже был отображен? Я никогда этого не знал... - person Michael Horn; 21.11.2019
comment
Я привык заходить в терминал, так как много работаю с узлом, и в этом случае это, конечно, было бы невозможно. - person Michael Horn; 21.11.2019
comment
Я не уверен, что он может измениться после оценки, но он говорит, что значение объекта слева было снято при регистрации, значение ниже было оценено только что., вот ответ, который объясняет это. - person Emile Bergeron; 21.11.2019
comment
Вместо того, чтобы добавлять разделы EDIT в свой ответ, просто удалите все, что вы хотели бы переформулировать, Stack Overflow имеет интерфейс истории редактирования, где мы могли бы изучить, чтобы понять, какие комментарии были оставлены здесь. - person Emile Bergeron; 21.11.2019
comment
В таком случае то, что я сказал, действительно имеет место, верно? console.log является асинхронным, потому что он медленный. Заданное значение может быть оценено немедленно, но если значение является указателем, то это не имеет значения, потому что объект, на который делается ссылка, может измениться до того, как журнал действительно появится. - person Michael Horn; 21.11.2019
comment
Это еще не медленно. Если вы регистрируете копию (глубокую или сериализованную как JSON), она будет доступна немедленно. Несмотря на то, что он интерактивный и с характером JS, где объекты являются ссылками (не совсем, но достаточно близко), консоль может проверять вложенные ссылки позже, когда пользователь расширяет их. - person Emile Bergeron; 21.11.2019
comment
Ах понял - спасибо, я обновил свой ответ - person Michael Horn; 21.11.2019
comment
Также обратите внимание, что после расширения Chrome выглядит как поверхностная копия, поэтому изменения больше не отражаются. - person Emile Bergeron; 21.11.2019