react quill TypeError:moduleClass不是构造函数

问题描述 投票:0回答:1

我正在尝试在我的

react-quill
项目中使用
nextJS
但收到此错误:


 1 of 1 unhandled error

Unhandled Runtime Error
TypeError: moduleClass is not a constructor

Call Stack
SnowTheme.addModule
node_modules\quill\dist\quill.js (6130:0)
SnowTheme.addModule
node_modules\quill\dist\quill.js (6774:0)
eval
node_modules\quill\dist\quill.js (6122:0)
Array.forEach
<anonymous>
SnowTheme.init
node_modules\quill\dist\quill.js (6120:0)
new Quill
node_modules\quill\dist\quill.js (1163:0)
ReactQuill.createEditor
node_modules\react-quill\lib\index.js (223:0)
ReactQuill.instantiateEditor
node_modules\react-quill\lib\index.js (187:0)
ReactQuill.componentDidMount
node_modules\react-quill\lib\index.js (152:0)
commitLifeCycles
node_modules\react-dom\cjs\react-dom.development.js (20663:0)
commitLayoutEffects
node_modules\react-dom\cjs\react-dom.development.js (23426:0)
HTMLUnknownElement.callCallback
node_modules\react-dom\cjs\react-dom.development.js (3945:0)
Object.invokeGuardedCallbackDev
node_modules\react-dom\cjs\react-dom.development.js (3994:0)
invokeGuardedCallback
node_modules\react-dom\cjs\react-dom.development.js (4056:0)
commitRootImpl
node_modules\react-dom\cjs\react-dom.development.js (23151:0)
unstable_runWithPriority
node_modules\scheduler\cjs\scheduler.development.js (468:0)
runWithPriority$1
node_modules\react-dom\cjs\react-dom.development.js (11276:0)
commitRoot
node_modules\react-dom\cjs\react-dom.development.js (22990:0)
performSyncWorkOnRoot
node_modules\react-dom\cjs\react-dom.development.js (22329:0)
eval
node_modules\react-dom\cjs\react-dom.development.js (11327:0)
unstable_runWithPriority
node_modules\scheduler\cjs\scheduler.development.js (468:0)
runWithPriority$1
node_modules\react-dom\cjs\react-dom.development.js (11276:0)
flushSyncCallbackQueueImpl
node_modules\react-dom\cjs\react-dom.development.js (11322:0)
flushSyncCallbackQueue
node_modules\react-dom\cjs\react-dom.development.js (11309:0)
scheduleUpdateOnFiber
node_modules\react-dom\cjs\react-dom.development.js (21893:0)
dispatchAction
node_modules\react-dom\cjs\react-dom.development.js (16139:0)
checkForUpdates
node_modules\use-subscription\cjs\use-subscription.development.js (85:0)
eval
node_modules\next\dist\shared\lib\loadable.js (183:44)
Set.forEach
<anonymous>
LoadableSubscription._update
node_modules\next\dist\shared\lib\loadable.js (183:24)
eval
node_modules\next\dist\shared\lib\loadable.js (164:17)

这里的代码显示了如何导入它以及如何渲染它:

import React, { useState, useEffect, useCallback } from 'react';
import 'react-quill/dist/quill.snow.css';
import { Box, TextField, Button, Typography, Input } from '@mui/material';
import { getStorage, ref, uploadBytes, getDownloadURL } from 'firebase/storage';
import { getFirestore, collection, addDoc } from 'firebase/firestore';
import dynamic from 'next/dynamic';

const ReactQuill = dynamic(() => import('react-quill'), { ssr: false, loading: () => <p>Loading...</p> });
const Quill = dynamic(() => import('react-quill'), { ssr: false, loading: () => <p>Loading...</p> });
const ImageUploader = dynamic(() => import('quill-image-uploader'), { ssr: false, loading: () => <p>Loading...</p> });

const CreatePost = () => {
  const [titles, setTitles] = useState({
    title_ar: '',
    title_en: '',
    title_fr: '',
    title_tr: '',
  });
  const [body, setBody] = useState('');
  const [mainImage, setMainImage] = useState(null);
  const [uploading, setUploading] = useState(false);

  const storage = getStorage();
  const db = getFirestore();

  useEffect(() => {
    if (Quill && Quill.register) {
      Quill.register('modules/imageUploader', ImageUploader);
    }
  }, []);

  const handleTitleChange = useCallback((e) => {
    const { name, value } = e.target;
    setTitles((prevTitles) => ({ ...prevTitles, [name]: value }));
  }, []);

  const handleEditorChange = useCallback((content) => {
    setBody(content);
  }, []);

  const handleMainImageChange = (e) => {
    setMainImage(e.target.files[0]);
  };

  const uploadImage = async (image) => {
    if (!image) {
      throw new Error('No image provided');
    }
    
    const storageRef = ref(storage, `images/${image.name}`);
    await uploadBytes(storageRef, image);
    return getDownloadURL(storageRef);
  };

  const uploadInBodyImage = async (image) => {
    if (!image) {
      return Promise.reject(new Error('No image provided'));
    }

    const storageRef = ref(storage, `images/${image.name}`);
    return uploadBytes(storageRef, image).then(() => {
      return getDownloadURL(storageRef).then((url) => {
        return url;
      });
    }).catch((error) => {
      console.error('Error uploading image or getting URL:', error);
      throw error;
    });
  };

  const modules = {
    toolbar: [
      [{ 'header': '1'}, {'header': '2'}, { 'font': [] }],
      [{ 'list': 'ordered'}, { 'list': 'bullet' }],
      ['bold', 'italic', 'underline'],
      ['link', 'image'],
      ['clean']
    ],
    imageUploader: {
      upload: async (file) => {
        try {
          const url = await uploadInBodyImage(file);
          return url;
        } catch (error) {
          console.error('Image upload failed:', error);
          throw error;
        }
      },
    },
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    setUploading(true);

    try {
      let mainImageUrl = '';
      if (mainImage) {
        mainImageUrl = await uploadImage(mainImage);
      }

      await addDoc(collection(db, 'Article'), {
        ...titles,
        body,
        mainImageUrl,
        createdAt: new Date(),
      });

      alert('Article created successfully!');
      setTitles({
        title_ar: '',
        title_en: '',
        title_fr: '',
        title_tr: '',
      });
      setBody('');
      setMainImage(null);
    } catch (error) {
      console.error('Error creating article:', error);
      alert('Failed to create article.');
    } finally {
      setUploading(false);
    }
  };

  return (
    <Box sx={{ p: 3 }}>
      <Typography variant="h5" gutterBottom>Create a New Article</Typography>
      <form onSubmit={handleSubmit}>
        <Box mb={2}>
          <TextField
            fullWidth
            label="Title (Arabic)"
            name="title_ar"
            value={titles.title_ar}
            onChange={handleTitleChange}
            variant="outlined"
          />
        </Box>
        <Box mb={2}>
          <TextField
            fullWidth
            label="Title (English)"
            name="title_en"
            value={titles.title_en}
            onChange={handleTitleChange}
            variant="outlined"
          />
        </Box>
        <Box mb={2}>
          <TextField
            fullWidth
            label="Title (French)"
            name="title_fr"
            value={titles.title_fr}
            onChange={handleTitleChange}
            variant="outlined"
          />
        </Box>
        <Box mb={2}>
          <TextField
            fullWidth
            label="Title (Turkish)"
            name="title_tr"
            value={titles.title_tr}
            onChange={handleTitleChange}
            variant="outlined"
          />
        </Box>
        <Box mb={2}>
          <Typography variant="h6" gutterBottom>Body</Typography>
          <ReactQuill
            value={body}
            onChange={handleEditorChange}
            modules={modules}
            style={{ height: '400px' }}
          />
        </Box>
        <Box mb={2}>
          <Input
            type="file"
            accept="image/*"
            onChange={handleMainImageChange}
            fullWidth
          />
        </Box>
        <Button type="submit" variant="contained" color="primary" disabled={uploading}>
          {uploading ? 'Uploading...' : 'Create Article'}
        </Button>
      </form>
    </Box>
  );
};

export default CreatePost;

javascript reactjs node.js react-native next.js
1个回答
0
投票

您在 Next.js 项目中遇到的带有

react-quill
的错误似乎与 Quill 模块的注册方式有关。如果模块系统未按预期工作,则可能会发生这种情况,这可能是由于 Next.js 处理模块导入的方式与传统 React 项目不同所致。

您可以尝试执行以下几个步骤来解决该问题:

1.确保正确导入
react-quill

确保正确导入

react-quill
,如下所示:

import dynamic from 'next/dynamic';

const ReactQuill = dynamic(() => import('react-quill'), { ssr: false });
import 'react-quill/dist/quill.snow.css';

ssr: false
选项禁用
react-quill
的服务器端渲染,这是必要的,因为Quill依赖于服务器上不可用的
window
对象。

2.检查鹅毛笔版本

确保您使用兼容版本的 Quill。有时,如果

react-quill
quill
之间不匹配,就会出现问题。确保您的
quill
依赖项已安装并且是最新的:

npm install quill@latest react-quill@latest

3.避免手动模块注册(如果适用)

如果您手动注册 Quill 模块(例如自定义模块),请确保操作正确。有时,如果模块系统与 Next.js 处理代码的方式不兼容,可能会出现错误。

4.设置示例

以下是如何在 Next.js 项目中设置

react-quill
的基本示例:

import dynamic from 'next/dynamic';
import 'react-quill/dist/quill.snow.css';

const ReactQuill = dynamic(() => import('react-quill'), { ssr: false });

const MyEditor = () => {
  return <ReactQuill theme="snow" />;
};

export default MyEditor;

5.调试特定模块

如果您自定义了 Quill 主题或模块,请尝试恢复到默认设置以隔离问题。这可以帮助确定问题是否在于特定的自定义。

6.清除缓存并重建

如果上述步骤不起作用,请尝试清除 Next.js 缓存并重建项目:

rm -rf .next
npm run build

7.用于进一步调试的控制台日志

添加一些

console.log
语句来检查到底在哪里触发了错误。它可能会为您提供有关有问题的模块的更多背景信息。

如果执行这些步骤后问题仍然存在,请随时分享更多详细信息,我们可以更深入地研究问题!

© www.soinside.com 2019 - 2024. All rights reserved.