0

当尝试在没有 YUP 的情况下进行表单验证时,我的表单会在组件安装时继续重新运行验证。我尝试更改代码 onValidationChange 和 validationOnBlur 更改,但在运行表单验证时似乎没有任何区别。有没有办法做到这一点?

目标是在 Blur 上为必填字段和 onSubmit 显示 toast 错误消息。任何帮助都会很棒!

import React, {useState, useEffect} from 'react';
import {useToast, useBreadcrumbs} from 'hooks';
import {PipelineState, IdState, selectedCustomer} from 'states';
import {useRecoilValue, useRecoilState} from 'recoil';
import {useHistory} from 'react-router-dom';
import {Formik, Form} from 'formik';
import {Pipelines} from 'api';
import {Input, DropDownInput, DateInput, ConfirmationDialog, FormattedInput, Scheduler, 
RadioButtonGroup} from 'components/Form';
import Toast from 'components/Toast';
import {FileList} from 'pages/FileGroups';
import {Contacts as CustomerIcon} from '@uitk/react-icons';
import {Button} from 'components/Styled';
import {Card} from '@uitk/react';
import {formatShortName} from 'utils';

const PipelineDetail = () => {
const history = useHistory();
const {toast, open, makeToast, eatToast} = useToast();
const [{customerId, pipelineId}, setIds] = useRecoilState(IdState);
const [{pipelineEnums, selectedPipeline}, setPipelineState] = useRecoilState(PipelineState);
const currentCustomer = useRecoilValue(selectedCustomer);
const isUpdate = pipelineId !== 'new';
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const breadcrumbs = useBreadcrumbs();

useEffect(() => {
    breadcrumbs.push(`/customers/${currentCustomer._id}`, currentCustomer.name);
}, [breadcrumbs, currentCustomer]);

const displayToastError = async msg => {
    throw new Error(msg);
};

const validateForm = values => {
    const errors = {};
    const {name, lob} = values;
    if (!name && !lob) {
        errors.name = 'Pipeline name is required';
        makeToast(displayToastError(errors.name));
    } else if (!name && lob) {
        errors.name = 'Pipeline name is required';
        makeToast(displayToastError(errors.name));
    } else if (name && !lob) {
        errors.lob = 'Lob is required';
        makeToast(displayToastError(errors.lob));
    }

    return errors;
};

const handleSubmit = async values => {
    const data = await makeToast(
        isUpdate ?
            Pipelines.update(customerId, values) :
            Pipelines.create(customerId, values),
        `Successfully ${isUpdate ? 'updated' : 'created'} pipeline ${values.name}`
    );
    setPipelineState();

    if (!isUpdate && !data.message) {
        setIds({customerId, pipelineId: data._id});
        history.push(`/customers/${customerId}/pipelines/${data._id}`);
    }
};

return (
    <>
        <Toast
            open={open}
            autoHideDuration={6000}
            severity={toast.severity}
            message={toast.message}
            onClose={eatToast}
        />
        <h1>
            <CustomerIcon size="l"/> {isUpdate ? selectedPipeline.name : 'New Pipeline'}
        </h1>
        <Formik
            enableReinitialize
            initialValues={selectedPipeline}
            validateOnBlur={false}
            validateOnChange={false}
            validate={validateForm}
            onSubmit={handleSubmit}
        >
            {({setFieldValue, setValues, values}) => (
                <Card>
                    <Form>
                        <div className="grid" justify="space-between">
                            {!isUpdate &&
                                <FormattedInput
                                    name="name"
                                    label="Pipeline Name"
                                    onChangeFormatter={event => {
                                        const formattedInput = formatShortName(event.target.value);
                                        setFieldValue('name', formattedInput);
                                    }}
                                />}
                            {isUpdate ?
                                <Input
                                    readOnly
                                    name="lob"
                                    label="LOB"
                                /> :
                                <DropDownInput
                                    items={pipelineEnums.lob}
                                    readOnly={isUpdate}
                                    name="lob"
                                    label="LOB"
                                />}
                            <RadioButtonGroup
                                items={pipelineEnums.runType}
                                name="runType"
                                label="Run Pipeline"
                                readOnly={isUpdate}
                                selectedType={selectedPipeline.runType}
                                labelKey={{immediate: 'As soon as validated', scheduled: 'Based on schedule'}}
                                onChange={e => setFieldValue('runType', e.target.value)}
                            />
                            {isUpdate ??
                                <Input
                                    readOnly
                                    value={`${currentCustomer?.shortName}/${selectedPipeline?.name}`}
                                    label="Pipeline Path"
                                />}
                            <DateInput
                                name="holdPipelineStartDate"
                                label="Hold Start"
                                onChange={(_, value) => setFieldValue('holdPipelineStartDate', value)}
                            />
                            <DateInput
                                name="holdPipelineEndDate"
                                label="Hold End"
                                onChange={(_, value) => setFieldValue('holdPipelineEndDate', value)}
                            />
                            <Input
                                name="watchDuration"
                                label="File Watch Duration"
                                type="number"
                            />
                        </div>
                        <Scheduler
                            schedules={values?.schedules}
                            setCron={(cronString, index) => {
                                setFieldValue(`schedules[${index}].cronExpression`, cronString);
                            }}
                            setInterval={interval => values?.schedules.forEach((_, i) => {
                                setFieldValue(`schedules[${i}].interval`, interval);
                            })}
                            setGrouped={isGrouped => setFieldValue('scheduleGroup', isGrouped)}
                            grouped={values?.scheduleGroup}
                            deleteSchedule={index => setValues({
                                ...values,
                                schedules: values?.schedules?.filter((_, i) => i !== index)
                            })}
                            addSchedule={() => setValues({
                                ...values,
                                schedules: values?.schedules?.concat({
                                    interval: values?.schedules?.[0]?.interval ?? 'daily',
                                    cronExpression: '0 0 * * *'
                                })
                            })}
                        />
                        <div className="row">
                            <Button type="submit" color="secondary">
                                Save Pipeline
                            </Button>
                            <Button
                                isDisabled={!isUpdate}
                                onPress={() => setDeleteDialogOpen(true)}
                            >
                                Delete Pipeline
                            </Button>
                        </div>
                    </Form>
                </Card>
            )}
        </Formik>
        <p/>
        {isUpdate && <FileList/>}
        <ConfirmationDialog
            actions={[
                {
                    text: 'confirm',
                    color: 'secondary',
                    action: async () => {
                        await Pipelines.del(customerId, pipelineId);
                        setIds({customerId, pipelineId: undefined, fileId: undefined});
                        history.push(`/customers/${customerId}`);
                        setPipelineState();
                    }
                },
                {text: 'cancel'}
            ]}
            open={deleteDialogOpen}
            title="Delete Pipeline"
            handleClose={() => setDeleteDialogOpen(false)}
        >
            Are you sure you want to permenantly delete this Pipeline?
        </ConfirmationDialog>
    </>
);
};

export default PipelineDetail;
4

0 回答 0