Откройте консоль введите в два поля значение, когда они больше или равны 8, меняем класс кнопки, но когда происходит проверка на длину, и мы уберем один символ, в state у нас по факту 7 но при получении длины у нас 8 и состояние кнопки остается активное, через setTimeout работает но это костыль.
Спасибо за помощь, готовый компонент тут => stackblitz.com/edit/template?file=components%2FForm.js
Откройте консоль, можно увидеть длину поля логин.
Дело в том что setState
- асинсхронная операция, и когда ты вызываешь getStateValues
сразу после setState
, то .state
внутри getStateValues
показывает еще не обновившееся значение.
Что можно сделать дешево, но с потенциальными проблемами в будущем: отказаться от использования this.state
внутри getStateValues
. Вместо этого в getStateValues
делать как setState
текущему компоненту, так и делать setState
родительскому.
Если ситуация позволяет лучше возьми решение для state management. Такое как redux
или mobx
. Тогда оба компонента (и инпут и кнопка) будут смотреть на значение из state management решения.
Не вышло, тебе не сложно подправить в моем решении. Пожалуйста. Посмотрю где протупил. Спасибо большое.
Не ожидай что я в будущем буду писать код за тебя. Только в качестве исключения https://template-htkamg.stackblitz.io
Я полнотью избавился от getStateValues
, а действия которые выполняла эта функция, перенес в handleChange
.
Мне не нравится это решение, и его надо будет переделывать чтобы оно поддерживало поведение для clearAllVules
. Наверное менее мерзкий вариант будет если ты все обновления состояния будешь пропускать через одну и ту же функцию, которая будет вызывать stateButton
.
Спасибо большое, но код не смог посмотреть))
Так открывается у тебя?
Так да, спасибо огромное, изучу детально, Надеюсь когда то буду писать хороший код, очень много прилагаю к этом усилий. Пока это полный треш((
Подскажите пожалуйста, как работать с вложенным state ??
state = {
form: {
login: '',
password: ''
}
}
Когда пишу вот так получаю ошибку, this.setState({[form.login]: ‘1234’}).
this.setState({
form: {
login: 'kokoko'
}
})
Спасибо, вот еще нашел https://vanslaars.io/post/setstate-lenses/
Работаю с Ramda.JS удобно.
Автор предлагает
- Дополнительную абстракцию (lenses)
- Думать терминами композиций функций. Ничего не имею против, но для задачи, стоящей перед тобой (изменение вложенных свойств), это оверхед.
- Не предлагает решения как изменять сложные вложенные объекты (несколько вложенных свойств. Одно - длина логина-пароля, второе - результат валидации).
Я бы делал clone
потом deep-merge
this.state
и не парился бы с рамбдой. Реализаций обоих в интернете достаточно. Такой подход кажется проще тем что думать можно меньше. Все что происходит с объектом происходит в трех строчках и не размазано в абстракциях по файлу.
this.setState(deepMerge(clone(this.state), {
form: {
login: 'kokoko'
}
}))
Спасибо, а функции ‘deepMerge’ , ‘clone’ это с какой библиотеки?
Не из какой конкретной. Я использовал имена чтобы описать действия функций. Легкое гугление дает пригоршню результатов: https://www.npmjs.com/package/deepmerge
Вот этот выглядит неплохо. И имеет встроенную настройку которая делает clone
объектов. Так что можно обойтись одной функцией. Но все же убедись что она работает как ожидается (и клонирует и мержит объекты).
Понял, да у меня так вышло, что изменил в поле form: login: ‘test’, осталось у меня в поле form только login, поле password в нем нет((
Значит мой пример нерабочий. Пример с deepmerge
будет работать
К сожалению, код с вопросом не доступен (уже не тот :) ). Но по твоему ответу видно где у человека была проблема. Возможно я не прав или не правильно понимаю вопрос. Но решить проблему асинхронности можно, просто передав callback как второй параметер в setState.
this.setState({value: 'new value'}, getStateValues)
Так сработает. Проще и красивее. Спасибо