简体   繁体   中英

MathJax in React, how to make sure updates to the page render in Latex correctly?

For some context, in my HTML I have imported MathJax source code in the first script tag:

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <script type="text/javascript" async src="//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML">
MathJax.Hub.Config({
    tex2jax: {
        inlineMath: [["$", "$"], ["\\(", "\\)"]],
        displayMath: [["$$", "$$"]], ["\\[", "\\]"]
        processEscapes: true
    }
});
</script>
    <script type="text/javascript" src="https://cdnjs.loli.net/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />

    <title>Ne computational engine</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

And I created a React component:



class Latex extends React.Component{
  constructor(props){
    super(props)
    this.node = React.createRef();
  }

  componentDidMount(){
    this.renderMath();
  }

  componentDidUpdate(){
    this.renderMath();
  }

  renderMath(){
    window.MathJax.Hub.Queue([
      "Typeset",
      window.MathJax.Hub,
      this.node.current
    ]);
  }

  render(){
    const {text} = this.props;
    return <div ref = {this.node}> {this.props.children}</div>;
  }
}

export default Latex;

So that I can nest my App component inside it:

ReactDOM.render(
  <Latex>
    <App />
  </Latex>,
  document.getElementById('root')
);

It works fine when the component first mounts so if I have, say $$\phi$$ inside a tag in my app component, it will render in Latex completely fine.

However in another React component that fetches data from the backend after a form has been submitted then displays it, none of the displayed data renders in Latex.

To add the data I have the following component and helper functions, which is very messy, but works fine. (aside from the fact mathjax doesn't seem to be rendering the text into Latex)

class CLI extends React.Component{
  constructor(props){
    super(props)
    this.state = {value: '',
                  interepreted: '',
                label: ''}

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);

  }

  handleChange(event){
    this.setState({value: event.target.value})
  }

  handleSubmit(event){

    event.preventDefault()
    const url = "/input"

    const ul = document.getElementById("ul-info")
    let resp = ""
  fetch(url+"/commands", {method: "POST", body: JSON.stringify(this.state.value),
  headers: new Headers({
    "content-type": "application/json"
  })}
  ).then(function(response) {
  resp = response
  response.json().then(function(data) {

    console.log(data);
    process_commands(ul,data)


  });
})
.catch(function(error) {
  console.log("Fetch error: " + error);
});
  }

  render(){
    return(
      <form onSubmit = {this.handleSubmit}>
        <label>
          <textarea value ={this.state.value}
            onChange = {this.handleChange} draggable = "false" cols = "70" rows = "2"/>
            <input type = "submit" value = "=" />

        </label>

      </form>
    )
  }
}

alongside the following helper functions:

function createNode(element){
  return document.createElement(element);
}

function append(parent,el){
  return parent.appendChild(el);
}

function process_commands(ul,data){
  var n;
  var i;
  var j;
  var k;
  for(n = 0; n<data.info.length;n++){
    if(data.labels[n] != null){
    let label = createNode("h2");
    label.innerHTML = `${data.labels[n]}`;
    append(ul,label);
    }
    if(data.labels[n] == "zeroes" || data.labels[n] == "partialderivative" || data.labels[n] == "partialintegral"){
    for(i = 0; i <data.info[n].length;i++){
      let sublabel = createNode("h3");
      sublabel.innerHTML = `${data.info[n][i][0]}`;
      append(ul,sublabel);
      for(j = 0; j<data.info[n][i][1].length; j++){
        let sublabel_function  = createNode("h4");
        sublabel_function.innerHTML = `${data.info[n][i][1][j][0]}`;
        append(ul, sublabel_function);
        for(k=0; k<data.info[n][i][1][j][1].length; k++){
          let solution = createNode("p");
          solution.innerHTML = `${data.info[n][i][1][j][1][k][0]}` + " : " + `${data.info[n][i][1][j][1][k][1]}`;
          append(ul,solution)
        }
      }
    }
  }
  }
}

But the Latex component won't render any of these newly created tags into Latex. I'm thinking that maybe I'm using Mathjax in a way that it is not intended or that I'm adding new HTML tags in a way that is incompatible with the LatexReact component's componentdidUpdate() method. I've been trying to figure out how to resolve this for hours, and I've followed other posts on here for MathJax but none of them addressed the issue (or none of the fixes changed anything).

(Just a reminder, the data displays perfectly fine, but in regular text, not in Latex)

As per my investigation Mathjax not typesetting even though there is change in children, simple check here is to pass one prop to Latex component either it is datetime or something just change that prop every time where there is change in your DOM, so LATEX component will get prop change so it will trigger MathJax typesetting, it worked for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM