React.js: после обновления формы невозможно получить обновленное значение (`componentWillReceive`) внутри компонента

Мы получаем с сервера форму, которую мы позволяем пользователю редактировать, и используем lodash _.set(object, path, value) для обновления частей этой формы в зависимости от того, какую часть формы обновляет пользователь.

Мы пытаемся получить текущее значение, задав состояние внутри компонента, но получаем эту ошибку;

Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops

Наша функция выглядит так:

onChange = ({ form }) => {
const { path, editKeyword } = this.props;
const inputValue = form[editKeyword];

let prevForm = this.props.form;

// update the object using
const updatedForm = _.set(prevForm, path, inputValue);

// action
this.props.setCurrentForm(updatedForm); };

Мы также безуспешно пробовали следующее:

onChange = ({ form }) => {
const { path, editKeyword } = this.props;
const inputValue = form[editKeyword];
console.info("input value ", inputValue);

let prevForm = this.props.form;

const updatedForm = _.set(prevForm, path, inputValue);

// when we try to update local state
this.setState({ form: updatedForm}) };

Кому-нибудь повезло с этим?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
63
1

Ответы 1

Ваша функция onChange срабатывает при изменении некоторых значений формы. Я не знаю, что делает функция setCurrentForm, но если она изменяет данные, относящиеся к форме, у нас здесь бесконечный цикл. Пользователь изменил текстовое значение формы, onChange срабатывает и запускает функцию setCurrentForm. Последнее изменение формы текстового значения, и функция onChange снова запускается. Думаю, в этом проблема.

Спасибо. Да, setCurrentForm пытается установить обновленную форму в состояние. Мы попытались использовать componentWillReceiveProps, но не смогли вернуть обновленное состояние в качестве реквизита. Мы попытались поместить свое действие в функцию onChange, и она правильно меняет состояние, когда пользователь вводит значение. Но когда мы закончим ввод, он вернется к пустому строковому значению, поскольку он не может получить обновленное состояние для компонента в качестве реквизита, а затем функция onChange снова запускает действие, потому что значение ввода пусто.

Mikael . 25.11.2018 03:10

Есть ли способ обойти это и установить обновленную форму в состояние, чтобы мы могли вернуть ее, не вызывая бесконечный цикл или значение, которое будет установлено как пустое?

Mikael . 25.11.2018 03:11

Конечно, постарайтесь отделить текущий ввод пользователя и его обработку от состояния. Позвольте логике формы работать внутри себя и обновлять форму только тогда, когда пользователь отправляет ее. Вчера сделал то же самое: форму для добавления элемента с несколькими тегами ввода. Но они не связаны с состоянием, они получают свои начальные значения как реквизиты, и когда пользователь нажимает кнопку «Отправить», моя функция onSave запускает отправку (действие) для обновления магазина. Здесь должен быть своего рода буфер между пользовательским вводом и состоянием, иначе цикл неизбежен.

Max Kurtz 25.11.2018 10:02

и обновлять форму только тогда, когда пользователь отправляет ее. ===== Я имел в виду это, извините: и обновляйте STATE только тогда, когда пользователь отправляет FORM.

Max Kurtz 25.11.2018 13:44

Спасибо! извиняюсь за поздний ответ. Мы пытаемся использовать onChange вместо submit. Мы создали песочницу кода; codeandbox.io/s/oo3qknl296 Наше требование состоит в том, чтобы мы получали исходное состояние formData с сервера, и нам нужно обновить определенную его часть, используя только путь (например, task[0].title или task.title, как в примере). Мы достигли этой функциональности и поместили ее в функцию onChange, как вы можете видеть в песочнице. Однако, если раскомментировать, где мы пытаемся установить обновленное состояние, мы увидим ошибку Maximum update depth exceeded...

Mikael . 28.11.2018 23:38

UPD: совет для понимания: при перезагрузке песочницы смотрите в консоль. Следующая строка после «Консоль была очищена» идет строка «входное значение не определено», - это вывод console.info из обработчика onChange. Итак, как мы видим, onChange запускается реакцией до того, как пользователь взаимодействует с формой. Реагировать на переданное состояние компоненту и запускать событие onChange. Поместите изменение состояния внутри onChange, и наш цикл будет выглядеть так: redux -> react-> component-> form-> onChange-> STATE CHANGES -> redux -> react ... - теперь вы знаете, что будет дальше :-)

Max Kurtz 29.11.2018 00:39

Потрясающий! Спасибо за это и за разъяснение шлейфа! Оставшаяся проблема для нас заключается в том, что мы используем onChange для запуска функции автосохранения обновленной формы. Есть ли способ по-прежнему использовать onChange, избегая этого цикла? Поскольку у нас (в соответствии с бизнес-требованиями) не может быть фактической кнопки «отправить», я не уверен, без использования onChange, как отслеживать изменения в форме, чтобы мы могли автоматически запускать функцию автосохранения.

Mikael . 29.11.2018 01:23

Извините, я зря потратил ваше время. Вот решение: codeandbox.io/s/9lkmwo61v4. Измените входы и посмотрите на Консоль.

Max Kurtz 29.11.2018 11:29

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