在Next.js项目中集成React Quill ImageResize模块时遇window未定义错误
解决Next.js中React Quill添加ImageResize模块时的window未定义问题
问题根源:Next.js是服务端渲染(SSR),服务端环境不存在window对象。你当前代码里直接在顶层导入ImageResize和Quill并执行注册,这部分逻辑会在服务端运行,所以触发ReferenceError: window is not defined。
修复步骤:
- 把ImageResize的导入和Quill注册放到客户端环境执行
利用Next.js的dynamic导入,在加载ReactQuill的同时,仅在客户端完成ImageResize模块的注册。 - 避免在服务端访问Quill相关API
调整modules配置中parchment的获取方式,确保只在客户端执行。
修改后的完整代码:
import { useState, useEffect } from 'react' import dynamic from 'next/dynamic' import 'react-quill/dist/quill.snow.css' import styles from '../styles/Components/TextEditor.module.scss' // 动态导入ReactQuill,同时在客户端注册ImageResize模块 const ReactQuill = dynamic(() => import('react-quill').then(async (mod) => { const Quill = mod.Quill // 仅在客户端导入并注册ImageResize const ImageResize = (await import('quill-image-resize-module-react')).default Quill.register('modules/imageResize', ImageResize) return mod }), { ssr: false } ) interface TextEditorParams { onChange: (value: string) => string | void placeholder?: string error?: boolean defaultValue?: string | undefined required?: boolean } const TextEditor = ({ onChange, placeholder, error, defaultValue, required }: TextEditorParams) => { const [errorState, setErrorState] = useState<boolean | undefined>(false) const [modules, setModules] = useState<any>(null) useEffect(() => { let shouldUpdate = true if (shouldUpdate) { setErrorState(error) } return () => { shouldUpdate = false } }, [error]) // 在客户端初始化modules配置,确保Quill已加载 useEffect(() => { import('react-quill').then(({ Quill }) => { setModules({ toolbar: { container: [ [{ header: [1, 2, 3, 4, 5, 6, false] }], ['bold', 'italic', 'underline', 'strike'], [{ list: 'ordered' }, { list: 'bullet' }], [{ align: [] }], ['link', 'image'], ['clean'] ] }, imageResize: { parchment: Quill.import('parchment'), modules: ['Resize', 'DisplaySize', 'Toolbar'] } }) }) }, []) const changeValue = (value: string) => { onChange(value) } // 确保modules加载完成后再渲染ReactQuill if (!modules) return null return ( <div className={styles.editor}> <ReactQuill modules={modules} defaultValue={defaultValue} onChange={(value) => changeValue(value)} placeholder={`${placeholder} ${required ? '*' : ''}`} className={errorState ? 'textEditor__error' : 'textEditor'} /> </div> ) } export default TextEditor
关键修改说明:
- 把
ImageResize的导入和Quill.register放到dynamic导入ReactQuill的回调里,用async/await确保执行顺序,同时dynamic设置ssr: false,这部分逻辑只会在客户端执行。 - 用
useState保存modules配置,在useEffect里(客户端环境)初始化,避免在服务端访问Quill.import。 - 渲染时先判断
modules是否存在,避免ReactQuill加载前传入未定义的modules。
内容的提问来源于stack exchange,提问作者Romanas
相关产品推荐
相关产品推荐

