I wrote an app using HTML which can render MathJax from script tag. Now I moved to React but the MathJax equation is not rendering at all.
I included a script(given below) in the ponentDidMount()
, ponentWillMount()
and ponentDidUpdate()
functions, but it's not rendering.
The MathJax script is getting fetched, but it's not ing back with the script with the configuration and other fonts needed to render the equations which used to e earlier.
I also tried bringing in the MathJax React plugin() too.
The code I used in the above methods:
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "/MathJax/MathJax.js"; // use the location of your MathJax
var config = 'MathJax.Hub.Config({' +
'extensions: ["tex2jax.js"],' +
'jax: ["input/TeX","output/HTML-CSS"]' +
'});' +
'MathJax.Hub.Startup.onload();';
if (window.opera) {script.innerHTML = config}
else {script.text = config}
document.getElementsByTagName("head")[0].appendChild(script);
})();
Earlier I used to have a simple page like
<script src=<MathJax link> />
<span>Some Equation</span>
</html>
Is this because of MathJax not even recognizing the content in the page?
I wrote an app using HTML which can render MathJax from script tag. Now I moved to React but the MathJax equation is not rendering at all.
I included a script(given below) in the ponentDidMount()
, ponentWillMount()
and ponentDidUpdate()
functions, but it's not rendering.
The MathJax script is getting fetched, but it's not ing back with the script with the configuration and other fonts needed to render the equations which used to e earlier.
I also tried bringing in the MathJax React plugin(https://www.npmjs./package/react-mathjax) too.
The code I used in the above methods:
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "/MathJax/MathJax.js"; // use the location of your MathJax
var config = 'MathJax.Hub.Config({' +
'extensions: ["tex2jax.js"],' +
'jax: ["input/TeX","output/HTML-CSS"]' +
'});' +
'MathJax.Hub.Startup.onload();';
if (window.opera) {script.innerHTML = config}
else {script.text = config}
document.getElementsByTagName("head")[0].appendChild(script);
})();
Earlier I used to have a simple page like
<script src=<MathJax link> />
<span>Some Equation</span>
</html>
Is this because of MathJax not even recognizing the content in the page?
Share Improve this question edited May 17, 2019 at 12:52 SLePort 15.5k3 gold badges39 silver badges45 bronze badges asked May 17, 2019 at 12:41 ChandramowliChandramowli 851 silver badge6 bronze badges 1-
1
You can also use a package to handle this I have written better-react-mathjax which you can use either altogether (and just care about the math content) or to handle the downloading of MathJax (and then use
Hub
orstartup
properties (depending on version)) and do the work manually in your React ponent. The docs contain plenty of examples. – fast-reflexes Commented Apr 2, 2021 at 9:19
3 Answers
Reset to default 2My guess is - you need to run Mathjax parser MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
after script loads.
Try to modify your script like this:
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "/MathJax/MathJax.js"; // use the location of your MathJax
var config = 'MathJax.Hub.Config({' +
'extensions: ["tex2jax.js"],' +
'jax: ["input/TeX","output/HTML-CSS"]' +
'});' +
'MathJax.Hub.Startup.onload();';
if (window.opera) {
script.innerHTML = config
} else {
script.text = config
}
script.addEventListener('load', function() {
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
})
document.getElementsByTagName("head")[0].appendChild(script);
})();
Formula rendering can only happen after MathJax has loaded all needed resources and finished initialization. This is why m51's solution is not correct, as it listens to the script element's load event. At that time MathJax is not guaranteed to be initialized.
You would need to use the offical ready
callback MathJax provides. The following example assumes you're using the current version MathJax 3.1.x (see MathJax documentation). Note that the following script element needs to e before loading the MathJax library.
<script>
window.MathJax = {
startup: {
ready: () => {
MathJax.startup.defaultReady();
// MathJax is initialized and you can trigger a typeset.
}
}
};
</script>
At that point in time MathJax typesetting is possible. But it might be necessary to delay typesetting further as there's no guarantee React has finished creating and inserting the HTML nodes.
So, you will need to account for two situations:
- MathJax initializes first, React is not done rendering.
- React is done rendering first, MathJax initialization still pending.
Depending on the situation you would need to have to delay the typesetting either in MathJax ready callback (Situation 1) or in a React lifecycle method (Situation 2).
There are many possible solutions to this. One could be, to use a mix of global variables and setTimeout
to orchestrate the flow. Others involve the use of promises. But the specific solutions to this are out of scope of this answer.
I remend using a library that abstracts away this and other problems: react-mathjax-node
Disclaimer: I'm the author of react-mathjax-node.
Like others mentioned, it is possible that Mathjax is loaded and finishes typesetting before React gets the content needed to be typeset on the page. Essentially, I think, you have a race between React loading content to be typeset and Mathjax typesetting.
A simple solution is to wait till Mathjax is loaded and then set some flag in the ponent state that lets React know that Mathjax is loaded. Setting the state would call ponentDidUpdate
and here is where you should typeset again. Here is a little ponent I wrote,
class App extends Component {
constructor(props) {
super(props);
this.state = {
readyToTypeset: false,
mathjaxConfig: {
startup: {
ready: () => {
window.MathJax.startup.defaultReady();
this.setState({ readyToTypeset: true });
}
}
}
};
}
ponentDidMount() {
window.MathJax = this.state.mathjaxConfig;
let script = document.createElement("script");
script.defer = true;
script.src = "https://cdn.jsdelivr/npm/mathjax@3/es5/tex-svg.js";
document.head.appendChild(script);
}
ponentDidUpdate() {
if (this.state.readyToTypeset)
window.MathJax.typesetPromise();
}
render() {
return String.raw`$$x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$$`;
}
}