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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:06:18