I am trying to Render Math Equation in a React Component with MathJax. It actually worked well if I pre-render it within the HTML file, but it is a mess when i try rendering it in React.
Here's my code
class Latex extends React.Component {
constructor(props) {
super(props);
}
componentDidMount(){
MathJax.Hub.Queue(['Typeset', MathJax.Hub, ReactDOM.findDOMNode(this)]);
}
componentDidUpdate() {
MathJax.Hub.Queue(['Typeset', MathJax.Hub, ReactDOM.findDOMNode(this)]);
}
render() {
//dangerouslySetInnerHTML={{__html: this.props.children}}
return (
<h5 dangerouslySetInnerHTML={{__html: this.props.children}}></h5>
);
}
}
Math Display both in Regular HTML and React Element
I used a combination of algebra.js and react-mathjax libraries to get it working in ES6. Because all these other packages are poorly maintained. For react-mathjax please use this repo.
Here's an example for showing fractions:
import React from 'react';
import { Fraction, toTex } from 'algebra.js';
import { Node, Context } from 'react-mathjax';
function Formula(props) {
return (
<Context input="tex">
<Node inline>{props.tex}</Node>
</Context>
);
}
export default function FractionDisplay() {
const a = new Fraction(1, 5);
const b = new Fraction(2, 7);
const answer = a.multiply(b);
const question = <Formula tex={`${toTex(a)} × ${toTex(b)} = ${toTex(answer)}`} />;
return (
<div>
{question}
</div>
);
}
Been a couple years, but if anyone is looking for a functional + mathjax3 based approach there is this repo:
https://github.com/jpribyl/react-hook-mathjax
demo of it is available at https://johnpribyl.com/react-hook-mathjax/
Usage is like this:
import React from "react";
import Tex2SVG from "react-hook-mathjax";
function App() {
return (
<div className="App">
<header className="App-header">
<Tex2SVG display="inline" latex="e^{i \pi} + 1 = 0" />
</header>
</div>
);
}
export default App;
import React from "react";
import Tex2SVG, { MathJaxProvider } from "react-hook-mathjax";
// This object contains the default options, more info at:
// http://docs.mathjax.org/en/latest/options/output/svg.html
const mathJaxOptions = {
svg: {
scale: 1, // global scaling factor for all expressions
minScale: .5, // smallest scaling factor to use
mtextInheritFont: false, // true to make mtext elements use surrounding font
merrorInheritFont: true, // true to make merror text use surrounding font
mathmlSpacing: false, // true for MathML spacing rules, false for TeX rules
skipAttributes: {}, // RFDa and other attributes NOT to copy to the output
exFactor: .5, // default size of ex in em units
displayAlign: 'center', // default for indentalign when set to 'auto'
displayIndent: '0', // default for indentshift when set to 'auto'
fontCache: 'local', // or 'global' or 'none'
localID: null, // ID to use for local font cache (for single equation processing)
internalSpeechTitles: true, // insert <title> tags with speech content
titleID: 0 // initial id number to use for aria-labeledby titles
}
}
function App() {
return (
<div>
<MathJaxProvider options={mathJaxOptions} />
<div className="App">
<header className="App-header">
<Tex2SVG display="inline" latex="e^{i \pi} + 1 = 0" />
</header>
</div>
</div>
);
}
export default App;
import React from "react";
import Tex2SVG from "react-hook-mathjax";
function App() {
const [inputValue, setInputValue] = React.useState(
"G_{\\mu\\nu} + \\Lambda g_{\\mu\\nu} = \\kappa T_{\\mu\\nu}",
);
return (
<div className="App">
<header className="App-header">
<h3>React Hook MathJax</h3>
<input
type="text"
defaultValue={inputValue}
onChange={e => setInputValue(e.target.value)}
/>
<div className="tex-container">
<Tex2SVG class="tex" tabindex={-1} latex={inputValue} />
</div>
</header>
</div>
);
}
export default App;
import React from "react";
import Tex2SVG from "react-hook-mathjax";
const getErrorFromHTML = (html) =>
html.children[1].firstChild.firstChild.attributes["data-mjx-error"].value;
function App() {
const [inputValue, setInputValue] = React.useState(
"G_{\\mu\\nu} + \\Lambda g_{\\mu\\nu} = \\kappa T_{\\mu\\nu}",
);
const [lastValidInput, setLastValidInput] = React.useState("");
const [error, setError] = React.useState(null);
const hasError = error !== null;
return (
<div className="App">
<header className="App-header">
<h3>React Hook MathJax</h3>
<input
className={`${hasError ? "error" : ""}`}
type="text"
defaultValue={inputValue}
onChange={e => {
setInputValue(e.target.value);
setError(null);
}}
/>
<div className="tex-container">
<Tex2SVG
class="tex"
tabindex={-1}
latex={hasError ? lastValidInput : inputValue}
onSuccess={() =>
setLastValidInput(hasError ? lastValidInput : inputValue)
}
onError={html => setError(getErrorFromHTML(html))}
/>
</div>
{hasError && <div>hint: {error}</div>}
</header>
</div>
);
}
export default App;
MathJaxProvider props:options Object, optionalTex2SVG props:latex string, requiredsvg''onSuccess (HTMLElement) => void, optionalsvg - it receives the html object generated by MathJax(html: HTMLElement) => {}onError (HTMLElement) => void, optionalsvg - it receives the html object generated by MathJax(html: HTMLElement) => {}Other html attributes {[key: string]: any} optionalclass - not className etcIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With