Wagtail中Draftail编辑器添加脚注功能报错求助
扩展Wagtail Draftail编辑器添加脚注功能及React报错排查
我来帮你梳理这个问题的排查方向,并给出修正后的实现代码。你遇到的React Error #130本质是组件渲染时传入了未定义的元素,结合你的代码来看,主要有几个关键问题需要修复:
一、报错核心排查点
- PropTypes未正确引入:你的
footnote.js里使用了PropTypes但没有从Wagtail的全局环境中获取,Wagtail后台已经内置了PropTypes,不需要额外导入,直接调用全局对象即可。 - Python类方法语法错误:
FootnoteEntityElementHandler的get_attribute_data方法缺少闭合的括号和大括号,导致后端语法错误,进而影响前端实体解析逻辑。 - Draft.js API调用逻辑问题:
Modifier.applyEntity的返回值是ContentState,你的代码在传递给EditorState.push时存在参数错误,导致EditorState更新失败。 - React JSX属性错误:JSX规范中应该用
className而非原生HTML的class属性,这是React的语法要求。
二、修正后的完整代码
1. wagtail_hooks.py 修正版
先确保导入必要模块,修复语法错误:
from wagtail import hooks from wagtail.rich_text import features from wagtail.rich_text.converters.html_to_contentstate import InlineEntityElementHandler from wagtail.utils.widgets import DOM @hooks.register('register_rich_text_features') def register_footnote_feature(features): features.default_features.append('footnote') """ Registering the `footnote` feature, which uses the `FOOTNOTE` Draft.js entity type, and is stored as HTML with a `<span data-footnote>` tag. """ feature_name = 'footnote' type_ = 'FOOTNOTE' control = { 'type': type_, 'label': '$', 'description': 'Footnote', } features.register_editor_plugin( 'draftail', feature_name, features.EntityFeature( control, js=['js/footnote.js'], css={'all': []} ) ) features.register_converter_rule('contentstate', feature_name, { 'from_database_format': {'span[data-footnote]': FootnoteEntityElementHandler(type_)}, 'to_database_format': {'entity_decorators': {type_: footnote_entity_decorator}}, }) def footnote_entity_decorator(props): """ Draft.js ContentState to database HTML. Converts the FOOTNOTE entities into a span tag. """ return DOM.create_element('span', { 'data-footnote': props['footnote'], }, props['children']) class FootnoteEntityElementHandler(InlineEntityElementHandler): """ Database HTML to Draft.js ContentState. Converts the span tag into a FOOTNOTE entity, with the right data. """ mutability = 'MUTABLE' def get_attribute_data(self, attrs): """ Take the ``footnote`` value from the ``data-footnote`` HTML attribute. """ return { 'footnote': attrs['data-footnote'], } # 修复:添加缺失的闭合括号和大括号
2. footnote.js 修正版
修复PropTypes引用、EditorState更新逻辑和JSX属性:
const React = window.React; const Modifier = window.DraftJS.Modifier; const EditorState = window.DraftJS.EditorState; const PropTypes = window.PropTypes; // 从Wagtail全局环境获取PropTypes class FootnoteSource extends React.Component { componentDidMount() { const { editorState, entityType, onComplete } = this.props; const currentContent = editorState.getCurrentContent(); // 创建新实体并应用到选中内容 const contentWithEntity = currentContent.createEntity( entityType.type, 'MUTABLE', { footnote: '' } // 初始化footnote数据,可后续扩展输入功能 ); const entityKey = contentWithEntity.getLastCreatedEntityKey(); const newContent = Modifier.applyEntity( currentContent, editorState.getSelection(), entityKey ); const nextState = EditorState.push(editorState, newContent, 'apply-entity'); onComplete(nextState); } render() { return null; } } const Footnote = (props) => { const { children, entityKey, contentState } = props; const data = contentState.getEntity(entityKey).getData(); return ( <span role="button" className="FootnoteEntity"> <span className="FootnoteEntity__label" aria-hidden="true">[Footnote]</span> {children} </span> ); }; Footnote.propTypes = { entityKey: PropTypes.string.isRequired, contentState: PropTypes.object.isRequired, }; window.draftail.registerPlugin({ type: 'FOOTNOTE', source: FootnoteSource, decorator: Footnote, });
三、额外优化建议
- 如果需要让用户输入自定义脚注内容,可以扩展
FootnoteSource组件,添加模态框收集脚注文本后再更新实体数据。 - 可以给脚注标记添加自定义CSS样式,让编辑器内的脚注标识更显眼。
- 测试时建议开启Wagtail开发模式(
DEBUG=True),这样能看到未压缩的React错误详情,更便于后续排查问题。
内容的提问来源于stack exchange,提问作者Savel Mtrx
相关产品推荐
相关产品推荐

