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

状态更新时Jsx-Parser内的MathJax无法重新渲染问题求助

问题描述

在React项目中,点击单选按钮触发状态更新时,所有DOM及JSX元素都会重新渲染,但Jsx-Parser组件内的MathJax元素除外;Jsx-Parser组件外的MathJax元素可随状态更新正常重渲染。已通过React开发者工具验证状态变化,即使将tex设为状态变量,该问题仍存在。

相关代码:

import { useState } from "react";
import MathJax from "react-mathjax";
import "./App.css";
import equations from "./equations/equations";
import JsxParser from "react-jsx-parser";

function App() {
    const { lhospital } = equations;
    const sample = {
        problem: `\\lim_{x\\rightarrow 1}\\frac{x^2-1}{x^2+3x-4}`,
        choices: [`1/5`, `2/5`, `3/5`, `4/5`],
        answer: `1/5`,
        solution: `Using <strong>L'Hospital's Rule </strong> {${lhospital}}
                  </br>$\\lim_{x\\rightarrow 1}\\frac{x^2-1}{x^2+3x-4}=\\lim_{x\\rightarrow 1}\\frac{2x}{2x+3}
                  =\\lim_{x\\rightarrow 1}\\frac{2(1)}{2(1)+3}=\\frac{2}{5}$`,
    };

    const [choice, setChoice] = useState(0);
    // console.log(lhospital);

    const changeChoiceHandler = (event) => {
        setChoice(event.target.value);
    };
    function submitHandler(event) {
        event.preventDefault();
        console.log("submit");
    }

    const tex = `<p>Differentiate </p><MathJax.Provider><MathJax.Node formula={problem} /></MathJax.Provider>`;

    return (
        <MathJax.Provider>
            <JsxParser
                bindings={{
                    ...sample,
                }}
                components={{ MathJax }}
                jsx={tex}
            />

            <form onSubmit={submitHandler}>
                <label>
                    <input
                        type="radio"
                        value={sample.choices[0]}
                        onChange={changeChoiceHandler}
                        checked={choice === sample.choices[0]}
                    />
                    {sample.choices[0]}
                </label>
                <label>
                    <input
                        type="radio"
                        value={sample.choices[1]}
                        onChange={changeChoiceHandler}
                        checked={choice === sample.choices[1]}
                    />
                    {sample.choices[1]}
                </label>
                <label>
                    <input
                        type="radio"
                        value={sample.choices[2]}
                        onChange={changeChoiceHandler}
                        checked={choice === sample.choices[2]}
                    />
                    {sample.choices[2]}
                </label>
                <label>
                    <input
                        type="radio"
                        value={sample.choices[3]}
                        onChange={changeChoiceHandler}
                        checked={choice === sample.choices[3]}
                    />
                    {sample.choices[3]}
                </label>
                <input type="submit" value="submit" />
            </form>
            <MathJax.Node formula={`y=x`} />
        </MathJax.Provider>
    );
}

export default App;

原因分析

  • Jsx-Parser缓存机制:react-jsx-parser默认会缓存解析后的JSX结构,只要传入的jsx字符串未发生变化,它就不会重新解析渲染内部组件,导致MathJax元素无法触发更新。
  • MathJax.Provider嵌套冲突:你在tex字符串里嵌套了MathJax.Provider,而外层已经存在全局的MathJax.Provider,这种嵌套会导致内部MathJax实例无法正确感知外层状态变化,进而无法触发重渲染。
  • 绑定值的浅比较限制:虽然每次状态更新时bindings都是新对象,但Jsx-Parser对bindings的浅比较可能判断其内容无变化,内部组件也就不会响应更新。

解决方案

方案1:用Key强制Jsx-Parser重渲染

给Jsx-Parser添加与状态choice绑定的key属性,状态变化时key改变,React会销毁旧组件实例并创建新的,从而强制重新解析JSX并渲染MathJax元素:

<JsxParser
    key={choice}
    bindings={{
        ...sample,
    }}
    components={{ MathJax }}
    jsx={tex}
/>

方案2:移除内部的MathJax.Provider

外层已经有全局的MathJax.Provider,内部无需重复嵌套,修改tex字符串:

const tex = `<p>Differentiate </p><MathJax.Node formula={problem} />`;

方案3:让tex依赖状态动态更新

将tex设置为依赖状态的计算值,确保状态变化时tex内容更新,触发Jsx-Parser重新解析:

const tex = `<p>Differentiate (selected: ${choice}) </p><MathJax.Node formula={problem} />`;

方案4:手动触发MathJax刷新

利用Jsx-Parser的onRender钩子,在渲染完成后手动调用MathJax的排版方法:

<JsxParser
    bindings={{
        ...sample,
    }}
    components={{ MathJax }}
    jsx={tex}
    onRender={() => {
        window.MathJax?.typeset();
    }}
/>

内容的提问来源于stack exchange,提问作者joshuaebs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:55:39