Возникла проблема в передаче данных из компонента шагов настройки системы в модальное окно.
Итак, дано
1) Модальное окно. Экспротится 3 класса.
- само модальное окно - React.Component
- обёртка класса пассящего пропсы из опций вызова для программного рендера
- обёртка класса пассящего пропсы спредом {...this.props} - тоже React.Component, использующая апи портала
То есть вроде должно быть ок. Я могу отрендерить модалку и функционально - из какого-нибудь event, и завязаться на state в jsx шаблоне.
2) Компонент шагов настройки системы
Это самая начинка раздела. В нём заложен непростой state. В текущем исполнении он весь описан вручную, но чуть позже подъедет сервер и мержиться стейт будет из props, которые расставит apollo.
this.state = {
steps: {
[stepName]: {
status: "proccess",
forcedOpen: false,
summary: true,
places: {
[placeName]: {
label: "label",
logged: true,
openModal: false // это способ рендера <ModalRenderer/> по условию bool state в шаблоне,
logFields: {
[fieldName]: {
value: 'val'
}
}
}
}
}
Везде где ключ в квадратных скобках - есть соседние объекты под разными ключами. Для того, чтобы изменить стейт по нажатию на свитчер или кнопку, я получал его через полбэк, копировал, изменял и возвращал обратно. И везде это работало, а когда я к этому стейту привязал input в модальном окне, onChange этого инпута срабатывает, вносит изменения в state, и даже render-функция снова выполняется, но prop value в Input не меняется
У меня возникает ощущение что что-то я недопонял в setState
ё
/* Это кусок render-функции корневого компонента роута, в котором проблема*/
render() {
...
const renderLoginModalInners = (place, stepKey, placeKey) => {
if (stepKey !== 'alreadyHasProfile') return false;
return <div className='flex flex-col'>
{Object.keys(place.logFields).map(key => {
if (key === 'clientID')console.log(this.state.steps[stepKey].places[placeKey].logFields[key].value)
// let field = place.logFields[key];
return <Input key={key}
value={this.state.steps[stepKey].places[placeKey].logFields[key].value}
onChange={this.bindPlaceLogField.bind(this, stepKey, placeKey, key)}/>
})}
<Button disabled={!this.isAllPlaceFieldsFilled.bind(this, place)}><Trans i18nKey='auth.action.logon'/></Button>
</div>
}
...
const renderLogger = (place, stepKey, placeKey) => {
if (!place.openLogger) return;
return <ModalRenderer ...>{renderLoginModalInners(place, stepKey, placeKey)}</ModalRenderer>
}
}
Ну и setState, которое я не знаю как подружить с ассоциативными массивами
bindPlaceLogField(stepKey, placeKey, fieldKey, event) {
const value = event.target.value
this.setState((state) => {
console.log(state.steps[stepKey].places[placeKey].logFields[fieldKey].value)
state.steps[stepKey].places[placeKey].logFields[fieldKey].value = value;
return Object.assign(state)
}, () => {
console.log(this.state.steps[stepKey].places[placeKey].logFields[fieldKey].value)
})
}
bindSwitchPlace(stepKey, placeKey, value) {
this.setState((state) => {
let newState = Object.assign(state);
newState.steps[stepKey].places[placeKey].value = value;
return newState;
})
}
toggleLoginModal(stepKey, placeKey, value) {
this.setState((state) => {
state.steps[stepKey].places[placeKey].openLogger = value;
return Object.assign(state)
})
/*вариант программного рендера. Сначала я отрендерил компонент программно, и подумал что в этом причина */
// const {t} = this.props;
// new ModalCaller({
// title: `${t('markets.step.loginModal.title')} ${place.label}`,
// children: this.renderLoginModalInners(place, stepKey, placeKey), эта функция была методом компонента и возвращала кусочек jsx
// })
}
все console.log отрабатывают в нужное время - onchange вызывает if (key === 'clientID') console.log и value там уже изменённое, как и в updated-колбэке setState, но сам input не перерисовывается.