首页 > 解决方案 > 提交操作后如何拒绝我的formik表单重新渲染

问题描述

我面临一个问题,即当我提交表单时,无论是否成功,整个表单字段都会重置。所以我假设这是因为组件正在重新渲染。

我想在提交表单时,无论网络请求是否成功,我希望它仍然保持字段内容

下面是整个代码的样子:

import { Formik, FieldArray } from 'formik';
import * as Yup from 'yup';
import React, { useEffect } from 'react';
import * as Style from './create-lesson-form.styles';
import { ReactComponent as AddNewIcon } from '../../assets/add-new.svg';
import { ReactComponent as RemoveRecent } from '../../assets/remove-recent.svg';
import CustomButton from '../custom-button/custom-button.component';
import SimpleCheckBox from '../field-inputs/simple-checkbox/simple-checkbox.component';
import { createALessonNote } from '../../redux/lesson_note/lesson_note.actions';
import { LessonNotePayload } from '../../redux/lesson_note/lesson_note.types';
import { connect } from 'react-redux';
import { CreateLessonPropType } from './create-lesson-form.types';
import ToastAlert from '../toast/toast.components';
import { createStructuredSelector } from 'reselect';
import {
    selectLessonCreationIsSuccess,
    selectLessonNoteError,
    selectLessonNoteSuccess,
} from '../../redux/lesson_note/lesson_note.selector';
import { selectSubjects } from '../../redux/subject/subject.selector';
import { fetchSubjectAction } from '../../redux/subject/subject.action';
import { fetchLevelAction } from '../../redux/level/level.action';
import { selectLevels } from '../../redux/level/level.selectors';

const CreateLessonForm: React.FC<CreateLessonPropType> = ({
    createLessonNote,
    fetchSubjects,
    fetchLevels,
    lesson_note_error,
    lesson_note_success,
    isLessonCreated,
    subjects,
    levels,
}) => {
    const handleAddStepsField = (values: any, setValues: any) => {
        const steps = [...values.steps];
        steps.push('');
        setValues({ ...values, steps });
    };

    const handleAddParagraphField = (values: any, setValues: any) => {
        const paragraphs = [...values.paragraphs];
        paragraphs.push('');
        setValues({ ...values, paragraphs });
    };

    const handleDeleteParagraphFields = (values: any, setValues: any) => {
        const paragraphs = [...values.paragraphs];
        paragraphs.pop();
        setValues({ ...values, paragraphs });
    };

    const handleDeleteStepsFields = (values: any, setValues: any) => {
        const steps = [...values.steps];
        steps.pop();
        setValues({ ...values, steps });
    };

    const fetchFormValues = async (values: any) => {
        const lessonPayload: LessonNotePayload = {
            class_id: values.class,
            subject_id: values.subject,
            topic: values.topic,
            is_published: values.is_published,
            lesson_body: values.paragraphs,
            lesson_plan: values.steps,
        };
        await createLessonNote(lessonPayload);
    };

    useEffect(() => {
        fetchSubjects();
        fetchLevels();
    }, []);

    return (
        <Style.CreateLessonNoteContainer>
            {lesson_note_error.length ? <ToastAlert message={lesson_note_error} type="failure" /> : null}
            {isLessonCreated ? <ToastAlert message={lesson_note_success} type="success" /> : null}
            <Formik
                /**
                 *Declare field initial values
                 */
                initialValues={{
                    topic: '',
                    subject: '',
                    class: '',
                    is_published: false,
                    date_of_delivery: '',
                    paragraphs: [],
                    steps: [],
                }}
                /**
                 * validate form on client side
                 */
                validationSchema={Yup.object({
                    topic: Yup.string().required(),
                    subject: Yup.string().required(),
                    class: Yup.number().required(),
                    date_of_delivery: Yup.date().required(),

                    paragraphs: Yup.array().of(Yup.string().required()),
                    steps: Yup.array().of(Yup.string().required()),
                })}
                /**
                 * listen to user submit action
                 */
                onSubmit={async (values, { setSubmitting, resetForm }) => {
                    alert(values);
                    console.log(values);
                    await fetchFormValues(values);

                    if (isLessonCreated) {
                        resetForm();
                        console.log('reset form');
                    }

                    setSubmitting(false);
                }}
            >
                {({ values, setValues }) => (
                    <>
                        <Style.FormTag>
                            <Style.LessonBodyFooter>
                                <Style.LessonHeadInput>
                                    <Style.LessonParagraphHeader>
                                        <h3>Lesson Header</h3>
                                    </Style.LessonParagraphHeader>
                                    <Style.CustomTextInput label="Topic" name="topic" type="text" />

                                    <Style.CustomSelectDropdown label="Subject" name="subject">
                                        <option value={''} disabled selected>
                                            select subject
                                        </option>
                                        {subjects.map((subject) => {
                                            return (
                                                <option key={subject.id} value={subject.id}>
                                                    {subject.title}
                                                </option>
                                            );
                                        })}
                                    </Style.CustomSelectDropdown>

                                    <Style.CustomSelectDropdown label="Level" name="class">
                                        <option value={''} disabled selected>
                                            select level
                                        </option>
                                        {levels.map((level) => {
                                            return (
                                                <option key={level.id} value={level.id}>
                                                    {level.title}
                                                </option>
                                            );
                                        })}
                                    </Style.CustomSelectDropdown>

                                    <Style.CustomTextInput
                                        label="Date of delivery"
                                        name="date_of_delivery"
                                        type="date"
                                    />
                                </Style.LessonHeadInput>
                                <Style.LessonParagraphContainer>
                                    <Style.LessonParagraphHeader>
                                        <h3>Lesson Paragraphs</h3>
                                        <div>
                                            <RemoveRecent
                                                onClick={() => handleDeleteParagraphFields(values, setValues)}
                                            />
                                            <AddNewIcon onClick={() => handleAddParagraphField(values, setValues)} />
                                        </div>
                                    </Style.LessonParagraphHeader>
                                    <Style.LessonParagraphFieldContainer>
                                        <FieldArray name={'paragraphs'}>
                                            {() =>
                                                values.paragraphs.map((_, index) => {
                                                    return (
                                                        <Style.LessonParagraphFieldDiv key={index}>
                                                            <Style.CustomTextArea
                                                                label={`Paragraph ${index + 1}`}
                                                                name={`paragraphs.${index}`}
                                                            />
                                                        </Style.LessonParagraphFieldDiv>
                                                    );
                                                })
                                            }
                                        </FieldArray>
                                    </Style.LessonParagraphFieldContainer>
                                </Style.LessonParagraphContainer>
                                <Style.LessonStepContainer>
                                    <Style.LessonParagraphHeader>
                                        <h3>Lesson Steps</h3>
                                        <div>
                                            <RemoveRecent onClick={() => handleDeleteStepsFields(values, setValues)} />
                                            <AddNewIcon onClick={() => handleAddStepsField(values, setValues)} />
                                        </div>
                                    </Style.LessonParagraphHeader>
                                    <Style.LessonParagraphFieldContainer>
                                        <FieldArray name={'steps'}>
                                            {() =>
                                                values.steps.map((_, index) => {
                                                    return (
                                                        <Style.LessonParagraphFieldDiv key={index}>
                                                            <Style.CustomTextArea
                                                                label={`Step ${index + 1}`}
                                                                name={`steps.${index}`}
                                                            />
                                                        </Style.LessonParagraphFieldDiv>
                                                    );
                                                })
                                            }
                                        </FieldArray>
                                    </Style.LessonParagraphFieldContainer>
                                </Style.LessonStepContainer>
                            </Style.LessonBodyFooter>
                            <Style.LessonFormFooter>
                                <SimpleCheckBox name={'is_published'}>Publish Note</SimpleCheckBox>
                                <CustomButton type="submit">Submit</CustomButton>
                            </Style.LessonFormFooter>
                        </Style.FormTag>
                    </>
                )}
            </Formik>
        </Style.CreateLessonNoteContainer>
    );
};

const mapStateToProps = createStructuredSelector({
    lesson_note_error: selectLessonNoteError,
    isLessonCreated: selectLessonCreationIsSuccess,
    lesson_note_success: selectLessonNoteSuccess,
    subjects: selectSubjects,
    levels: selectLevels,
});

const mapDispatchToProps = (dispatch: any) => {
    return {
        createLessonNote: ({
            class_id,
            subject_id,
            topic,
            is_published,
            lesson_body,
            lesson_plan,
        }: LessonNotePayload) =>
            dispatch(
                createALessonNote({
                    class_id,
                    subject_id,
                    topic,
                    is_published,
                    lesson_body,
                    lesson_plan,
                }),
            ),
        fetchSubjects: () => dispatch(fetchSubjectAction()),
        fetchLevels: () => dispatch(fetchLevelAction()),
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(CreateLessonForm);

标签: javascriptreactjsreduxformikreact-forms

解决方案


推荐阅读