3

I am making a web editor using React & SlateJS. There are LaTex code in the editor content and I want the user to see the rendered LaTex equations. MathJax and KaTex have auto-rendering feature by loading them as CDNs. Once they are loaded, the content on html body is rendered. But they are not live-rendering when I modify the content.

So I have made a button that opens a modal which renders the un-editable edior content in a smaller window, and I want the LaTex codes to be rendered in the modal.

The APP component:

import {Editor} from 'slate-react';
import ReactModel from 'react-modal';
import RenderedEditorDialog from "./RenderedEditorDialog";

class APP extends React.component {

    ...

    render() {
        return (
            <div className={"editorContainer"}>
                <div className={"editor"}>
                    <Editor
                        autoFocus
                        ref={this.ref}
                        value={this.state.value}
                        onChange={this.onChange}
                        onKeyDown={this.onKeyDown}
                        renderMark={this.renderMarks}
                        renderBlock={this.renderBlock}
                    />
                </div>
                <ReactModal
                    isOpen={this.state.showMathDialog}
                    contentLabel="Rendered content"
                    onRequestClose={this.handleCloseMathDialog}
                >
                    <button onClick={this.handleCloseMathDialog}>Close Dialog</button>
                    <RenderedEditorDialog value={this.state.value}/>
                </ReactModal>
            </div>
        )
    }
}

RenderedEditorDialog (modal) component:

import {Editor} from 'slate-react';

class RenderedEditorDialog extends React.Component {
    // eslint-disable-next-line no-useless-constructor
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div>
                <Editor
                    value={this.props.value}
                    renderMark={this.renderMarks}
                    renderBlock={this.renderBlock}/>
            </div>
        )
    }
}

My question is how I can apply MathJax/KaTex to render the content in RenderedEditorDialog component?

Thanks in advance!

Xiaohui Liu
  • 51
  • 2
  • 6

1 Answers1

1

KaTeX can be applied to individual DOM elements on demand, instead of all at once, by calling renderMathInElement when desired. Calling this from componentDidUpdate should do the trick:

import {Editor} from 'slate-react';

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

    render() {
        return (
            <div ref={this.ref}>
                <Editor
                    value={this.props.value}
                    renderMark={this.renderMarks}
                    renderBlock={this.renderBlock}/>
            </div>
        )
    }

    componentDidUpdate() {
        renderMathInElement(this.ref.current, katexOptions);
    }
}

I'm more comfortable with hook-based components instead of classes, which would look like this:

function RenderedEditorDialog(props) {
    const ref = useRef();
    useEffect(() => {
        renderMathInElement(ref.current, katexOptions);
    });
    return (
        <div ref={ref}>
            <Editor
                value={props.value}
                renderMark={props.renderMarks}
                renderBlock={props.renderBlock}/>
        </div>
    )
};

I'm not sure whether you want this on RenderedEditorDialog or another more specific component, but this should give you the idea. For speed, you want to apply renderMathInElement to the smallest container that contains the updated math.

edemaine
  • 2,699
  • 11
  • 20