React-Admin RichTextInput集成TipTap图片扩展不生效问题
React-Admin RichTextInput 图片插入功能修复方案
核心问题定位
你当前的代码存在三个直接导致功能异常的问题:
- 单独调用
useEditor创建的编辑器实例,和RichTextInput内部实际渲染的实例不是同一个,自定义按钮的操作根本作用不到真实编辑器上,不仅图片按钮失效,你测试的HorizontalRules自定义按钮点击无响应也是这个原因。 ra-input-rich-text默认的HTML解析规则会过滤img标签,手动插入的img代码会被直接清除,RichTextField渲染内容时同样会拦截白名单外的标签。- 图片按钮点击事件里的
url变量未定义,就算实例匹配也会直接抛错。
分步修复
1. 配置编辑器扩展与解析规则,允许图片标签渲染
首先在文件头部补充缺失的依赖导入:
import StarterKit from '@tiptap/starter-kit'; import { useRichTextInputEditor } from 'ra-input-rich-text'; import ImageIcon from '@mui/icons-material/Image';
修改编辑器配置,注册Image扩展并放开img标签解析限制:
export const MyEditorOptions = { ...DefaultEditorOptions, extensions: [ // 先移除默认配置里的StarterKit,重新配置避免冲突 ...DefaultEditorOptions.extensions.filter(ext => ext.name !== 'starterKit'), StarterKit.configure({ ...DefaultEditorOptions.extensions.find(ext => ext.name === 'starterKit')?.options, html: { preserveWhitespace: 'full' } }), Image.configure({ inline: false, // 图片默认块级展示,避免行内嵌排版错乱 allowBase64: false, // 不需要base64图片可以保持关闭 HTMLAttributes: { class: 'rtf-image' } // 可自定义类名加样式 }) ], parseOptions: { preserveWhitespace: 'full' } };
同时修改内容展示侧的RichTextField配置,把img标签加入渲染白名单,否则详情页看内容时图片还是会被过滤:
<RichTextField source="body" stripTags={false} // 关闭默认的强制标签剥离 allowedTags={['p', 'br', 'strong', 'em', 'ul', 'ol', 'li', 'blockquote', 'hr', 'h1', 'h2', 'h3', 'a', 'img']} allowedAttributes={{ img: ['src', 'alt', 'title', 'width', 'height', 'class'], a: ['href', 'target', 'rel'] }} />
2. 实现图片插入按钮
不要自己初始化editor实例,用官方提供的useRichTextInputEditor hook拿组件内部的真实编辑器实例,保证操作能生效:
const ImageInsertButton = ({ size }) => { const editor = useRichTextInputEditor(); if (!editor) return null; const handleClick = () => { const imgUrl = window.prompt('请输入图片URL地址'); if (!imgUrl) return; // 简单校验URL合法性 try { new URL(imgUrl) } catch { alert('请输入有效的URL地址'); return; } // 插入图片到当前光标位置 editor.chain().focus().setImage({ src: imgUrl, alt: '' }).run(); }; return ( <ToggleButton value="image" aria-label="插入图片" title="插入图片" size={size} onClick={handleClick} selected={editor.isActive('image')} > <ImageIcon fontSize="inherit" /> </ToggleButton> ); };
3. 整合到自定义富文本组件
移除之前冗余的useEditor调用,把图片按钮放到工具栏对应位置即可:
export const MyRichTextInput = ({ size, ...props }) => { return ( <RichTextInput editorOptions={MyEditorOptions} toolbar={ <RichTextInputToolbar> <Box sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center', flexWrap: 'wrap', }} > <LevelSelect size={size} /> <FormatButtons size={size} /> <AlignmentButtons size={size} /> <ListButtons size={size} /> <LinkButtons size={size} /> <QuoteButtons size={size} /> <ClearButtons size={size} /> <ImageInsertButton size={size} /> </Box> </RichTextInputToolbar> } label="正文" source="body" {...props} /> ) };
补充说明
官方文档里HorizontalRules自定义按钮示例点击无响应,也是因为示例代码如果单独初始化editor实例,会和组件内部实例脱节,所有自定义工具栏按钮统一用useRichTextInputEditor拿实例就不会出现这类问题。
内容的提问来源于stack exchange,提问作者Diego Gaona
相关产品推荐
相关产品推荐

