When doing a React project, I want to render mathematical formulas on a webpage without using pre-packaged React components. I want to directly render the DOM using dynamic loading.

Mathjax@3 has made a major update, and the usage is different from version 2.x.

## Dynamically Loading JS in React#

The first thing to know is how to dynamically load JS. You can mount a new script node to the DOM using JavaScript.

Create a `script`

element, set the `src`

attribute to the URL you want to load, and then append the node to the body element.

Here is a function that encapsulates this process. You just need to pass the URL of the JS file you want to load and use the `.then`

method for subsequent operations.

```
export const loadJS = (url: string) =>
new Promise(function (resolve, reject) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
document.body.appendChild(script);
script.onload = function () {
resolve(`success: ${url}`);
};
script.onerror = function () {
reject(Error(`${url} load error!`));
};
});
```

In the place where you need to use it:

```
loadJS(url)
.then(() => {
// do something
})
.catch(() => {
// do something
});
```

## [email protected] Version#

First, here are some official reference links. This article may not be very clear.

- Loading and Configuring MathJax

https://docs.mathjax.org/en/v2.7-latest/configuration.html - Loading MathJax Dynamically

https://docs.mathjax.org/en/v2.7-latest/advanced/dynamic.html - Modifying Math on the Page

https://docs.mathjax.org/en/v2.7-latest/advanced/typeset.html

After loading Mathjax, we just need to render the DOM at the appropriate time.

Here's an example:

```
componentDidMount() {
const mathjaxUrl = 'https://cdn.bootcss.com/mathjax/2.7.4/MathJax.js?config=TeX-AMS_CHTML';
loadJS(mathjaxUrl).then(() => {
this.showMathjax();
});
}
componentDidUpdate () {
if (!(window as any).MathJax) {
(window as any).MathJax.Hub.Queue(['Typeset', (window as any).MathJax.Hub, ReactDOM.findDOMNode(this)]);
}
}
showMathjax = () => {
if ((window as any).MathJax) {
(window as any).MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$', '$']],
displayMath: [['$$', '$$']],
skipTags: ['script', 'noscript', 'style', 'textarea', 'code', 'a'],
},
CommonHTML: {
scale: 120,
linebreaks: { automatic: true },
},
'HTML-CSS': { linebreaks: { automatic: true } },
SVG: { linebreaks: { automatic: true } },
TeX: { noErrors: { disabled: true } },
});
} else {
setTimeout(this.showMathjax, 1000);
}
};
```

In version 2.x, we need to use `Mathjax.Hub.Config`

for configuration. The configurations are quite easy to understand. In `tex2jax`

, we set how to render mathematical formulas when they are wrapped in certain characters.

Inline formulas are wrapped in `$...$`

, and multiline formulas are wrapped in `$$...$$`

. We also specify which tags should not be rendered.

Then we set the rendering behavior for different modes. The JS file we loaded has a query `?config=TeX-AMS_CHTML`

, which indicates that we loaded the CHTML configuration. Different configurations have different display effects. See https://docs.mathjax.org/en/v2.7-latest/config-files.html

After loading `Mathjax`

, it will automatically render the page. However, for single-page applications, `Mathjax`

will not re-render when the DOM is updated. We need to use `MathJax.Hub.Queue(['Typeset', MathJax.Hub, ReactDOM.findDOMNode(this)]);`

to manually render the DOM. Add it to `componentDidUpdate`

.

## Mathjax@3 Version#

Here are the official documentation links:

- Configuring MathJax

http://docs.mathjax.org/en/v3.0-latest/options/index.html - MathJax in Dynamic Content

http://docs.mathjax.org/en/v3.0-latest/advanced/typeset.html

In version 3, the loading and configuration methods of `Mathjax`

are different.

Upgrading from v2 to v3: http://docs.mathjax.org/en/latest/upgrading/v2.html

You can directly load JS files with different configurations without using `?config=xxx`

. For example, load `https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js`

.

The `Mathjax.Hub`

methods have been removed. Now, you just need to assign a configuration object to `window.Mathjax`

to set the configuration.

The official documentation also provides a link to convert configurations: MathJax Configuration Converter

Here is my configuration:

```
(window as any).MathJax = {
tex: {
inlineMath: [['$', '$']],
displayMath: [['$$', '$$']],
},
options: {
skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'code', 'a'],
},
chtml: {
scale: 1.2,
},
startup: {
ready: () => {
(window as any).MathJax.startup.defaultReady();
(window as any).MathJax.startup.promise.then(() => {
console.log('MathJax initial typesetting complete');
});
},
},
};
```

After the Mathjax script is loaded, it reads the `window.Mathjax`

as the configuration and replaces it with the `Mathjax`

object, so you can call related functions.

When `Mathjax`

is initialized, it calls the `startup.ready`

method in the configuration, where you can provide prompts or other configurations.

The same problem exists: `Mathjax`

does not re-render when the DOM is updated. You need to use the `MathJax.typesetPromise()`

method. Set it in `componentDidUpdate`

.

```
componentDidUpdate() {
const MathJax = (window as any).MathJax;
if (MathJax) {
MathJax.typesetPromise && MathJax.typesetPromise();
}
}
```

This method is asynchronous. There is also a synchronous method with the same functionality: `MathJax.typeset()`

.