A math editor with React and Katex

Thursday, Mar 26 2015 in react

Most websites use LaTex to let users input mathematics. We are going to see how to build a LaTex input widget with React.

Two JavaScript libraries can transform LaTex input into proper mathematics: Mathjax and Katex. I chose Katex for this demo because it works out of the box as a npm package.

Usually, Katex scans the whole document to find latex strings to convert. We instead wish perform the conversion inside a React component as the user types.

We start by defining an Input component that stores the user input into its state and passes it to the MathDisplay component. For this demo we use ES6 classes:

class Input extends React.Component {
  constructor() {
    super();
    this.state = {text: ''};
    this.updateText = this.updateText.bind(this);
  }

  updateText(event) {
    var nText = event.target.value;
    this.setState(function () {
      return {text: nText};
    });
  }

  render() {
    var text = this.state.text;
    return (
      <div>
        <input type="text" 
         onChange={this.updateText}/>
         <MathDisplay data={text}/>
      </div> );
  }
}

katex.renderToString() takes any LaTex text and returns a string representation of the corresponding HTML; the MathDisplay component calls katex.renderToString() and displays the output in its render() function.

By default, React escapes its output. To insert the raw HTML string into the document, we use dangerouslySetInnerHTML. This property is dangerous because it exposes to cross site scripting attacks: a malicious script could add any markup to the page through the input field. We should sanitize to prevent the user from inserting any unwanted markup in the page. Luckily, Katex should be doing that for us already.

class MathDisplay {
  constructor(props) {
    this.props = props;
  }

  render() {
    var math = katex.renderToString(this.props.data);
    return (<p dangerouslySetInnerHTML={ {__html: math} }/>);
  }
}

That’s it! If we add the KaTex fonts and CSS files, we have now a fully working math input and display combo.