Значения Formik не обновляются с состоянием

Вот шаблон формы, которую я пишу с помощью Formik и react-bootstrap. Я нахожу очень странную ошибку: если я инициализирую свое состояние фиктивными данными в конструкторе, оно работает нормально; но если я вызову setState с точно такими же данными в componentDidMount для имитации вызова API, он ужасно сломается.

В частности, я обнаружил, что массив переменной состояния alertVehicles может иметь ненулевую длину, но соответствующая переменная Formik values.alertVehicles может быть пустой. Прямо сейчас форма, как она написана, не отображает флажки. Если я использую alertVehicles вместо values.alertVehicles в своем защитном предложении, то он вылетает с ошибкой Cannot read property 'selected' of undefined.

import React, {Component} from 'react';
import Form from 'react-bootstrap/Form';
import { Formik } from 'formik';
import Button from 'react-bootstrap/Button';


class Alerts extends Component {
    constructor(props) {
        super(props);
        this.loadAlertData = this.loadAlertData.bind(this);
        this.state = {
            alertRecipient: {},
            alertId: '',
            alertVehicles: []
        }
    }

    componentDidMount(){
        this.loadAlertData();
    }

    loadAlertData(){
        // this will be an API call eventually, obviously.
        // if this is initialised in the constructor then everything works!
        this.setState( {
            alertRecipient: {
                name: 'Rob',
                simNumber: '0123456789',
            },
            alertId: 1,
            alertVehicles: [
                {id: 1, vrn: 'vehicle A', selected: true },
                {id: 2, vrn: 'vehicle B', selected: false },
                {id: 3, vrn: 'vehicle C', selected: true }
            ]
        })
    }

    render() {
        const { alertRecipient, alertId, alertVehicles } = this.state;
        return (
            <>
                <Formik
                    initialValues = {{ alertRecipient, alertId, alertVehicles }}
                    onSubmit = { values => {
                            window.alert(JSON.stringify(values))
                        }
                    }
                    render = {({values, handleChangeEvent, handleSubmit}) => (
                        <Form onSubmit = {handleSubmit}>
                            <Form.Label>Name</Form.Label>
                            <Form.Control
                                type = "text"
                                name = "alertRecipient.name"
                                value = {values.alertRecipient.name}
                                onChange = {handleChangeEvent}
                            />
                            <Form.Label>Phone number</Form.Label>
                            <Form.Control
                                type = "text"
                                name = "alertRecipient.simNumber"
                                value = {values.alertRecipient.simNumber}
                                onChange = {handleChangeEvent}
                            >
                            </Form.Control>
                            <Form.Label>Vehicles</Form.Label>
                            {
                                //get an error if we just use alertVehicles.length here??
                                values.alertVehicles.length === 0 ? null : alertVehicles.map((veh, index) => (

                                    <Form.Check type = "checkbox"
                                                key = {veh.id}
                                                label = {veh.vrn}
                                                name = {`alertVehicles[${index}].selected`}
                                                checked = {values.alertVehicles[index].selected}
                                                onChange = { handleChangeEvent }
                                    />
                                ))
                            }
                            <Button type = "submit">Save</Button>
                        </Form>
                    )
                    }
                />
            </>
        )
    }

}

export default Alerts;

я не понимаю

  1. Почему код работает, когда я устанавливаю свои фиктивные данные в конструкторе, а не в componentDidMount
  2. Почему values.alertVehicles не синхронизировано с alertVehicles.

Заранее благодарю за любую помощь.

Поведение ключевого слова "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) для оценки ваших знаний,...
24
0
26 931
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

По какой-то причине это поведение Formik по умолчанию, и вам нужно указать свойство enableReinitialize, чтобы переопределить его: https://github.com/jaredpalmer/formik/issues/811

Это поведение по умолчанию настолько ненужно и тратит время

Aderemi Dayo 04.02.2021 16:36

@AderemiDayo, у вас есть какие-либо ссылки на его поведение по умолчанию? потому что это работа меня после enableReintialize=true в Formik

Mohd Qasim 13.10.2021 09:24

На самом деле это имеет смысл. В большинстве случаев вы не хотите стирать то, что пользователь может делать в форме только потому, что состояние изменилось. На самом деле вы, вероятно, захотите, если пользователь еще ничего не коснулся, но не после.

В любом случае они дают вам флаг, чтобы управлять им...

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