【问题标题】:'FieldArray' cannot be used as a JSX component'FieldArray' 不能用作 JSX 组件
【发布时间】:2022-06-15 08:32:48
【问题描述】:

在我的 next.js 项目中,我使用了 Formik 组件。但是它显示一个类型错误,即“'FieldArray'不能用作JSX组件。”我该如何解决?

错误是

 'FieldArray' cannot be used as a JSX component.
  Its element type 'ReactElement<any, any> | Component<FieldArrayConfig, any, any> | null' is not a valid JSX element.
    Type 'Component<FieldArrayConfig, any, any>' is not assignable to type 'Element | ElementClass | null'.
      Type 'Component<FieldArrayConfig, any, any>' is not assignable to type 'ElementClass'.
        The types returned by 'render()' are incompatible between these types.
          Type 'React.ReactNode' is not assignable to type 'import("/home/shoyon/WorkPlace/Practice/EmailSystem/view/node_modules/@types/react-transition-group/node_modules/@types/react/index").ReactNode'.
            Type '{}' is not assignable to type 'ReactNode'.ts(2786)

我的代码是:

import React, { useEffect, useState } from 'react'
import AttachmentForm from '@components/Forms/AttachmentForm'
import { ProjectActionType } from '@enums/enums'
import { Button, Divider, Grid, Link, Typography } from '@mui/material'
import { Notify } from '@utils/common'
import { FormikTextField, MultiValueInput } from '@utils/FormElements'
import { FieldArray, Form, Formik, FormikProps } from 'formik'
import * as Yup from 'yup'
import { useRouter } from 'next/router'
import { createTemplate, getTemplateById } from 'requests/templates'

interface pageProps {
    type: ProjectActionType
}

interface AttachmentValues {
    attachmentName: any;
    attachmentData: string;
}

interface FieldValues {
    projectId: number | null;
    title: string;
    cc?: string;
    bcc?: string
    templateName?: string;
    templateData?: string
    attachment?: AttachmentValues[] | [] | null;
}

const SingleTemplate = ({ type }: pageProps) => {
    const router = useRouter();
    
    const [data, setData] = useState<FieldValues>({
        projectId: null,
        title: '',
        templateName:'',
        templateData: '',
        cc: '',
        bcc: '',
        attachment: []
    });

    const validationSchema = Yup.object().shape({
        projectId: Yup.number().required('Field required'),
        title: Yup.string().required('Field required'),
        templateName: type === ProjectActionType.ADD ? Yup.mixed().required('File is required') : Yup.mixed(),
        templateData: Yup.string().required('Field required'),
        cc: Yup.string(),
        bcc: Yup.string(),
        attachment: Yup.array().of(
            Yup.object().shape({
                attachmentName: Yup.mixed().required('File is required'),
                attachmentData: type === ProjectActionType.ADD ? Yup.mixed().required('Data is required') : Yup.mixed(),
            })
        )
    });

    const getTemplateData = async (id: number)=> {
        let res = await getTemplateById(id);
        if (res?.statusCode === 200) setData({
            ...data,
            title: res.data.title,
            templateName: res.data.templateName,
            templateData: JSON.stringify(res.data.templateData),
            cc: res.data.cc,
            bcc: res.data.bcc,
            attachment: res.data.attachment
        });
        else Notify(res?.message, 'error');
    }

    const handleSubmit = async (values: FieldValues, setSubmitting: any) => {
        let res = await createTemplate(values);
        if (res?.statusCode === 201) Notify('Template added', 'success');
        else Notify(res?.message, 'error');
        setSubmitting(false);
    }

    useEffect(()=>{
        if(router.query.id) {
            const id = parseInt(router.query.id as string, 10);
            setData({...data, projectId: id});
            if(type === ProjectActionType.EDIT) getTemplateData(id);
        }
    // eslint-disable-next-line react-hooks/exhaustive-deps
    },[router])
    

    return (
        <React.Fragment>
            <Typography variant='h5' mb={4}>Email Settings</Typography>
            <Formik 
                enableReinitialize={true}
                initialValues={data}
                validationSchema={validationSchema} 
                onSubmit={(values, { setSubmitting }) => {
                    handleSubmit(values, setSubmitting);
                }}
            >
                {(props: FormikProps<any>) => {
                    const { values, touched, errors, handleBlur, handleChange, isSubmitting } = props
                    return (
                        <Form noValidate autoComplete="off">
                            ...

                            <Divider className='mb-6' />
                            <FieldArray name="attachment"
                                render={arrayHelpers => (
                                    <React.Fragment>
                                        {values.attachment && values.attachment.map((key: any, i: number) => (
                                            <AttachmentForm key={i}
                                                index={i}
                                                id={key}
                                                onDelete={() => arrayHelpers.remove(i)}
                                                values={values}
                                                touched={touched}
                                                errors={errors}
                                                handleBlur={handleBlur}
                                                handleChange={handleChange}
                                            />
                                        ))}
                                        <div className="flex">
                                            <Button variant="contained" color='info' className='mr-3' type='submit' disabled={isSubmitting}>Save</Button>
                                            <Button variant="contained" onClick={() => arrayHelpers.push({ attachmentName: '', attachmentData: '' })}>
                                                Add Attachment
                                            </Button>
                                        </div>
                                    </React.Fragment>
                                )}
                            />
                        </Form>
                    )
                }}
            </Formik>
        </React.Fragment>
    )
}

export default SingleTemplate

【问题讨论】:

标签: reactjs typescript next.js formik


【解决方案1】:

FieldArray 上的 render 方法需要返回单个根元素。通过使用React.Fragment,将返回多个元素。将 React.Fragment 更改为 div 应该可以解决该错误。

【讨论】:

  • 我尝试使用div,但同样的错误显示
  • @AbdullahAlMamun 你介意用一个简化的例子制作一个沙箱吗?
【解决方案2】:

我在typescript 上使用formikmaterial-ui 时遇到了同样的问题。

对我来说,react-is 版本有问题。

通过将以下内容添加到package.json 来解决它:

"overrides": {
  "react-is": "^17.2.0",
  "@types/react-is": "^17.0.0"
}

需要 npm >= 8 基于 this post

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-02
    • 2022-06-20
    • 2021-02-20
    • 2021-09-13
    • 1970-01-01
    • 2022-08-22
    • 2022-06-11
    • 2022-06-14
    相关资源
    最近更新 更多