React中解析HTML字符串并结合forwardRef调用Wiris解析函数问题
问题核心原因
- Wiris提供的
com.wiris.js.JsPluginViewer.parseElement方法要求传入真实DOM节点,你之前的代码传入了整个ref对象,调用自然失效 - 父组件冗余的ref数组维护逻辑导致ref绑定异常,同时useEffect依赖项配置错误,也会导致回调逻辑不触发
- 全局Wiris对象的加载时机如果晚于组件渲染,没有做空判断也会导致报错
方案1:子组件内部管理ref(推荐,无特殊需求优先用这个)
直接去掉冗余的forwardRef和父组件ref数组,子组件自己维护DOM引用,逻辑更清晰。
父组件Parser代码
import WirisWrapper from './WirisWrapper'; const Parser = ({ itemsArray }) => { return ( <div> {itemsArray.map((item, index) => item.type === 'math' ? ( <WirisWrapper key={index} mString={item.html} /> ) : ( <div key={index} dangerouslySetInnerHTML={{ __html: item.html}}> </div> ) )} </div> ); }; export default Parser;
子组件WirisWrapper代码
import { useRef, useEffect } from 'react'; const WirisWrapper = ({ mString }) => { // 子组件内部维护DOM引用 const wirisDomRef = useRef(null); useEffect(() => { // 兼容全局Wiris对象未加载完成的场景 const wirisInstance = window.com?.wiris?.js?.JsPluginViewer; if (!wirisDomRef.current || !wirisInstance) return; // 赋值HTML后调用解析方法,注意这里传入的是ref.current对应的DOM节点 wirisDomRef.current.innerHTML = mString; wirisInstance.parseElement(wirisDomRef.current, true, function () {}); }, [mString]); // 仅当公式字符串变更时重新执行解析 return <div ref={wirisDomRef}></div>; }; export default WirisWrapper;
方案2:保留父组件ref数组的修改方式
如果你确实需要在父组件中拿到所有Wiris元素的DOM引用,按如下修改即可:
父组件Parser代码
import { useRef } from 'react'; import WirisWrapper from './WirisWrapper'; const Parser = ({ itemsArray }) => { // 初始化ref数组,不要每次渲染都重置 const refs = useRef(new Array(itemsArray.length)); return ( <div> {itemsArray.map((item, index) => item.type === 'math' ? ( <WirisWrapper ref={(el) => (refs.current[index] = el)} key={index} mString={item.html} /> ) : ( <div key={index} dangerouslySetInnerHTML={{ __html: item.html}}> </div> ) )} </div> ); }; export default Parser;
子组件WirisWrapper代码
import { forwardRef, useRef, useEffect, useImperativeHandle } from 'react'; const WirisWrapper = forwardRef(({ mString }, parentRef) => { const innerRef = useRef(null); // 将内部DOM节点暴露给父组件的ref useImperativeHandle(parentRef, () => innerRef.current); useEffect(() => { const wirisInstance = window.com?.wiris?.js?.JsPluginViewer; if (!innerRef.current || !wirisInstance) return; innerRef.current.innerHTML = mString; wirisInstance.parseElement(innerRef.current, true, function () {}); }, [mString]); return <div ref={innerRef}></div>; }); // 配合forwardRef设置组件displayName方便调试 WirisWrapper.displayName = 'WirisWrapper'; export default WirisWrapper;
内容的提问来源于stack exchange,提问作者Er.Se
相关产品推荐
相关产品推荐

