Next.js中React Quill链接清理失效及相关报错问题
解决Next.js中react-quill的超链接与SSR兼容问题
1. 修复无协议链接自动补全HTTP/HTTPS
Quill的Link.sanitize方法负责处理链接格式化,我们需要重写它,但必须确保代码只在客户端浏览器环境执行,避免SSR时的document is not defined错误。
正确的重写方式
不要在组件顶层直接修改Quill,而是在组件的useEffect钩子(仅客户端执行)里修改:
import ReactQuill from 'react-quill'; import 'react-quill/dist/quill.snow.css'; import { useEffect } from 'react'; const MyEditor = () => { useEffect(() => { const Link = ReactQuill.Quill.import('formats/link'); const originalSanitize = Link.sanitize; Link.sanitize = function(value) { const sanitized = originalSanitize(value); // 检测是否为无协议的绝对链接(排除mailto、tel等特殊协议) if (sanitized && !/^(https?:\/\/|mailto:|tel:)/i.test(sanitized)) { return `https://${sanitized}`; } return sanitized; }; ReactQuill.Quill.register(Link, true); }, []); return ( <ReactQuill theme="snow" /> ); }; export default MyEditor;
2. 解决SSR时的document is not defined错误
上面的代码用useEffect确保修改逻辑只在客户端运行,因为useEffect不会在SSR阶段执行。如果仍有问题,改用Next.js的动态导入并禁用SSR:
正确的动态导入写法
不要直接导入Quill,而是动态导入整个react-quill组件,并关闭SSR:
import dynamic from 'next/dynamic'; // 禁用SSR,确保组件只在客户端渲染 const ReactQuill = dynamic(() => import('react-quill'), { ssr: false, loading: () => <p>加载编辑器中...</p> }); const MyEditor = () => { useEffect(() => { // 组件已在客户端加载,可安全访问ReactQuill.Quill const Link = ReactQuill.Quill.import('formats/link'); const originalSanitize = Link.sanitize; Link.sanitize = function(value) { const sanitized = originalSanitize(value); if (sanitized && !/^(https?:\/\/|mailto:|tel:)/i.test(sanitized)) { return `https://${sanitized}`; } return sanitized; }; ReactQuill.Quill.register(Link, true); }, []); return ( <ReactQuill theme="snow" /> ); }; export default MyEditor;
3. 解决动态导入后的Quill is undefined错误
这个错误通常是因为在组件挂载前就尝试访问ReactQuill.Quill,或者动态导入的组件还未加载完成。上面的useEffect是空依赖数组,会在组件挂载后执行,此时ReactQuill已加载完毕,可安全访问。
如果仍有问题,可添加加载状态判断:
import dynamic from 'next/dynamic'; import { useState, useEffect } from 'react'; const ReactQuill = dynamic(() => import('react-quill'), { ssr: false, loading: () => <p>加载编辑器中...</p> }); const MyEditor = () => { const [isEditorLoaded, setIsEditorLoaded] = useState(false); useEffect(() => { if (ReactQuill && ReactQuill.Quill) { setIsEditorLoaded(true); const Link = ReactQuill.Quill.import('formats/link'); const originalSanitize = Link.sanitize; Link.sanitize = function(value) { const sanitized = originalSanitize(value); if (sanitized && !/^(https?:\/\/|mailto:|tel:)/i.test(sanitized)) { return `https://${sanitized}`; } return sanitized; }; ReactQuill.Quill.register(Link, true); } }, [ReactQuill]); return isEditorLoaded ? <ReactQuill theme="snow" /> : <p>加载编辑器中...</p>; }; export default MyEditor;
关键注意事项
- 所有修改Quill的逻辑必须放在客户端执行(
useEffect或动态导入禁用SSR),避免SSR时访问浏览器API。 - 重写
Link.sanitize时,保留原方法的逻辑,仅补充协议补全逻辑,避免破坏原有功能。 - 动态导入时务必设置
ssr: false,让react-quill只在客户端渲染。
内容的提问来源于stack exchange,提问作者Siddhesh Nalawade
相关产品推荐
相关产品推荐

