React-Final-Form: установить initialValues из реквизита, состояние формы сбрасывается при смене реквизита
У меня есть компонент, который занимает balance
опора, и этот баланс пропел может меняться со временем.
Затем у меня есть React Final Form для отправки транзакции с обычным количеством полей для отправки, получателем... И в моем validate
Я просто проверяю, достаточно ли у пользователя баланса для отправки транзакции.
Однако, если мой баланс изменяется, когда пользователь что-то вводит, тогда вся форма сбрасывается. Как бы вы сбросили только часть состояния формы?
См. Этот код и окно для примера: https://codesandbox.io/s/jn69xql7y3:
- введите что-то
- подождите 5 с
- увидеть, что состояние формы снова пустое
0 ответов
Я просто столкнулся с этой проблемой с react-final-form
где форма полностью сбрасывается, когда любое изменение состояния происходит в компоненте оболочки.
Проблема здесь (из вашего codeandbox)
<Form
initialValues={{ amount: 0, balance }} <-- creates a new object on every render
Проблема в том, что когда initialValues
изменяет всю форму повторно инициализируется. По умолчанию все, что вы передаетеinitialValues
сравнивается с предыдущим с использованием неглубоких равенств, то есть сравнения ссылок.
Это означает, что если вы создаете новый объект в рендере, даже если он такой же, вся форма сбрасывается при изменении какого-либо состояния, функция рендеринга запускается повторно, и новый объект с новой ссылкой создается для initialValues
.
Чтобы решить общую проблему, если вы просто хотите отключить сброс формы, я просто переместил initialState
, который никогда не изменяется, на переменную, так что это одна и та же ссылка при каждом рендеринге и, следовательно, всегда кажется одинаковой для final-form с поведением по умолчанию. Я бы предпочел, чтобы конфигурация полностью отключила это поведение при повторной инициализации, но я не могу найти его в документации.
Однако, если вы действительно этого хотите, но вам нужно его изменить, поведение сравнения можно настроить с помощью initialValuesEqual
prop (документы здесь), чтобы провести глубокое сравнениеinitialValues
объект например.
Вы также можете использовать keepDirtyOnReinitialize
prop, чтобы сбросить только те части вашей формы, которые не были затронуты.
Я предполагаю, что какая-то комбинация вышеперечисленного может решить ваш вариант использования, в зависимости от того, какой именно UX вам нужен.
Добавляя к тому, что упомянул @davnicwil, мое решение useMemo()
подключить компоненты func:
const initialValues = useMemo(() => ({ amount: 0, balance }), [])
Используя useMemo
он создает только 1 объект в течение срока службы компонента, и последующие повторные отрисовки не приводят к перезаписи значений формы в initialValues.
Другое решение - использовать опору формы response-final-form initialValuesEqual={() => true}
<Form initialValues={{ amount: 0, balance }} initialValuesEqual={() => true} .../>
ссылка: https://github.com/final-form/react-final-form/issues/246