You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js项目引入react-quill后Jest测试报错求助

问题

使用Jest和react-testing-library测试Next.js应用时,原本正常的测试在加入react-quill组件后出现以下错误:

"Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of ForwardRef(LoadableComponent)."
"Error: Uncaught [Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object."

我通过Next.js的dynamic方法动态导入react-quill(设置ssr: false),并在react-hook-form的表单中使用该组件,代码示例如下:

import FormItemInner from "../../ui/reusable/customForm/FormItemInner"
import React, { FC, useState, useEffect } from 'react';
import dynamic from 'next/dynamic';
import { Controller } from "react-hook-form";
import { Form } from "react-bootstrap";
import ReportAttachment from "./ReportAttachment";
import { ValidationMessage } from "../../ui/reusable/Reusable";

const QuillNoSSRWrapper: any = dynamic(import('react-quill'), {
    ssr: false,
    loading: () => <p>Loading ...</p>,
})


const ProofOfConcept: FC<{ getFiles: any, register: any, errors: any, control: any, translate: any, authTranslate: any }> = ({ getFiles, register, errors, control, translate, authTranslate }) => {
    const [loaded, setLoaded] = useState(false);

    useEffect(() => {
        setLoaded(true)
    }, [])
    return (
        <div style={{ borderTop: '1px solid #BCBCBC59', paddingTop: '1rem' }}>
            <FormItemInner title={translate("impactTitle")} required description={translate('reportImpactDescription')}>
                <Form.Control
                    className="mb-4 gray_input"
                    id="inputReportImpact"
                    data-testid="inputReportImpact"
                    type="name"
                    {...register("impact", {
                        required: true,
                    })}
                />
                {errors?.impact?.type === "required" && (
                    <ValidationMessage
                        message={authTranslate("RequiredField")}
                    />

                )}
            </FormItemInner>
            <FormItemInner title={translate("summaryTitle")} required description={translate('reportSummaryDescription')}>
                <Controller
                    name="summary"
                    control={control}
                    render={({ field: { onChange, value }, }) => (
                        <QuillNoSSRWrapper className="wrapperClassName mb-4" theme="snow" value={value} onChange={onChange} />
                    )}
                />
            </FormItemInner>
            <FormItemInner title={translate("recommendationTitle")} required description={translate('reportRecommendationDescription')}>
                <Controller
                    name="recommendation"
                    control={control}
                    render={({ field: { onChange, value } }) => (
                        <QuillNoSSRWrapper className="wrapperClassName mb-4" theme="snow" value={value} onChange={onChange} />

                    )}
                />
            </FormItemInner>

            <FormItemInner title={translate("attachmentTitle")} description={translate('reportAttachmentDescription')}>
                <ReportAttachment getFiles={getFiles} translate={translate} />
            </FormItemInner>

        </div >
    )

}

export default ProofOfConcept
解决方案

这个错误源于Jest无法正确处理Next.js禁用SSR的动态导入组件,以下是三种可行的解决方式:

方法1:模拟react-quill组件

在测试文件顶部添加模拟代码,让Jest使用一个简易的替代组件,跳过真实Quill的加载逻辑:

jest.mock('react-quill', () => {
  return () => <div data-testid="mock-quill-editor" />;
});

这种方式简单高效,适合不需要测试Quill编辑器具体功能的场景。

方法2:修正动态导入的写法

react-quill的导出是默认导出,动态导入时需要明确指定获取默认导出,避免因导入方式导致组件类型错误:

const QuillNoSSRWrapper: any = dynamic(() => import('react-quill').then(mod => mod.default), {
  ssr: false,
  loading: () => <p>Loading ...</p>,
});

方法3:等待动态组件加载完成

如果需要测试真实的Quill组件行为,可在测试中使用waitFor等待动态组件加载完毕:

import { render, waitFor } from '@testing-library/react';

test('验证Quill编辑器渲染', async () => {
  const { getByTestId } = render(<ProofOfConcept {...你的props参数} />);
  await waitFor(() => expect(getByTestId('mock-quill-editor')).toBeInTheDocument());
});

注意:这种方式需要确保测试环境支持Quill的DOM依赖,若遇到环境兼容问题,还是推荐使用模拟组件的方式。

内容的提问来源于stack exchange,提问作者mostafa elbanna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:21:03