reactjsmathml

How to do interactive MathML with React?


Writing a math expression as text can make it quite ugly

<p>λy.xy</p>

results in this: unicode lambda expression

Doing it with MathML seems better

<math xmlns="http://www.w3.org/1998/Math/MathML">
    <mi>&lambda;</mi>
    <mi>y</mi>
    <mo>.</mo>
    <mi>x</mi>
    <mi>y</mi>
</math>

gives: MathML lambda expression

(On math stack exchange it's even nicer with the same MathML: lambda expression from math stack exchange, but I'm not sure yet how to get that without MathJax)

I want to have the nicer look in my React app, but it doesn't seem to accept the <math> tag. Is there a solution that would be similar to JSX and let me use React interactivity like the HTML below?

<math xmlns="http://www.w3.org/1998/Math/MathML">
    <mi onClick="console.log('hello')">&lambda;</mi>
    <mi>y</mi>
    <mo>.</mo>
    <mi>x</mi>
    <mi>y</mi>
</math>

Solution

  • The math element appears to be perfectly valid HTML, which means it should work just fine in JSX in React as well. The only issue I see in your JSX is with the mi element's onClick handler. You've specified a string value when it should be a function in JSX, e.g. change onClick="console.log('hello')" to onClick={() => console.log('hello')}.

    Example:

    function App() {
      return (
        <div className="App">
          <math xmlns="http://www.w3.org/1998/Math/MathML">
            <mi onClick={() => console.log('hello')}>&lambda;</mi>
            <mi>y</mi>
            <mo>.</mo>
            <mi>x</mi>
            <mi>y</mi>
          </math>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    const root = ReactDOM.createRoot(rootElement);
    
    root.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.0.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.0.0/umd/react-dom.production.min.js"></script>
    <div id="root" />