skip to Main Content

I am building a webapp that uses LaTeX writable by user in some input to dynamically show it into another div or replacing it in the same input.

I’ve been trying to use Mathquill with NextJS v13.3.0, and I found this npm package that solves that for React called "React-Mathquill" (https://www.npmjs.com/package/react-mathquill), but this does not work beacuse of SSR (Server Side Rendering) according to the author, and he suggest to import the package without SSR (https://github.com/viktorstrate/react-mathquill/issues/49). The thing is, I quite do not understand how to do this, I’ve read the documentation according to NoSSR (https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading#with-no-ssr) but seems a bit complex to understand and make unsure on how to do it.

If someone knows how to solve this or has a different solution with another library or something to show complex math equations (even without LaTeX) compatible with Next, I would thank you for share it

Here’s what I tried:

import React, { useState } from 'react'
import { addStyles, EditableMathField } from 'react-mathquill'

addStyles()

function Test() 
{
    const [latex, setLatex] = useState('\frac{1}{\sqrt{2}}\cdot 2')

    return (
        <div>

          <EditableMathField
            latex={latex}
            onChange={(mathField) => {
              setLatex(mathField.latex())
            }}
          />

          <p>{latex}</p>

        </div>
      )
}

export default Test

but this error shows up:

Server Error
ReferenceError: window is not defined

2

Answers


  1. Chosen as BEST ANSWER

    After researchig other libraries and some failure, I found MathJax and made this solution which reanalyze every element of the page when the specified LaTeX change:

    import Head from 'next/head';
    import { useEffect, useState } from 'react'
    
    function Test() 
    {
        const [latex, setLatex] = useState("");
    
        const handleChange = ( { target: { value } }) =>
        {   
            setLatex(value)
        }
    
        const mathJaxReanalyze = async () => 
        {
            if (typeof window !== 'undefined' && window.MathJax) 
            {
                try
                {
                    await window.MathJax.typesetPromise();
                }
                catch(e)
                {
                    console.log("MatJax error: " + e);
                }
            }
        }
    
        useEffect(() =>
        {
            mathJaxReanalyze();
        }, [latex])
    
        return (
            <>
                <Head>
                    <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
                    <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
                </Head>
    
                <div>
                    
                    <input onChange={handleChange}/>
    
                    <p>{latex}</p>
    
                </div>
            </>
        )
    }
    
    export default Test
    

    It is not as clean as using MathQuill would have been, but works for me

    EDIT: Recently noticed the comment with the solution, but I will leave this answer if someone finds it useful


  2. According to this post Next.js: window is not defined, some libraries do references to window just by being imported, so they must be used by another way, in this case, the function addStyles was the problem. Since MathQuill provides its stylesheet, I was able to add it from the public folder of the proyect this way

    import { useState } from 'react'
    import dynamic from 'next/dynamic';
    import Head from 'next/head';
    
    const EditableMathField = dynamic(() => import("react-mathquill"), { ssr: false })
    
    function Test() 
    {
        const [latex, setLatex] = useState('\frac{1}{\sqrt{2}}\cdot 2')
    
        return (
            <>
                <Head>
                     <link rel="stylesheet" href="/mathquill.css"/>
                </Head>   
    
                <div>
    
                    <EditableMathField
                        latex={latex}
                        onChange={(mathField) => 
                            {
                                setLatex(mathField.latex())
                            }}
                    />
    
                    <p>{latex}</p>
    
                </div>
            </>
          )
    }
    
    export default Test
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search