DEV Community

Kiran
Kiran

Posted on

Next JS 14 + Katex web app

If you are building a STEM web application, there is a certainty that you will need to render formulae, chemical reactions and equations. STEM audiences are used to writing these in LaTeX format. In this post, we will create a React component that can render these LaTeX equations with the help of the KaTeX library.

Latex equation to render

We will look at quadratic formula text for this blog post. If the text is

Given a general quadratic equation of the form
$$ax^{2} + bx + c = 0$$
with $x$ representing an unknown, with $a$, $b$ and $c$ representing constants, and with $a \ne 0$, the quadratic formula is:
$$x = \frac{-b \pm \sqrt{b^{2} - 4ac}}{2a}$$
Enter fullscreen mode Exit fullscreen mode

The above block of text should be rendered as
Image description

❗️Spoiler❗️

The code for this is available here: https://github.com/kirankulkarni/next-katex

Setup details

For this post, I have used.

  1. Next JS 14.0.4
    1. Using Javascript
    2. Using the App router
  2. Tailwind CSS 3.3.0
  3. Katex 0.16.9

Step 1: Install katex in your NextJS setup

npm i katex
Enter fullscreen mode Exit fullscreen mode

Step 2: Build a KatexSpan component that can render the equations

Step 2.1: Understanding Katex Auto Render extension usage.

We will be using the Katex Auto Render extension. This automatically detects equations in the child nodes and converts them into equations. You can find a detailed explanation here.

The auto render provides the function renderMathInElement that takes a DOM node reference and options. The function will recursively search for text nodes inside this element and render the math in them. refer to API for more info

Step 2.2: Create a KatexSpan component file

Ensure that it’s a client component by mentioning use client; as the first line of the file.

Step 2.3: Importing renderMathInElement function

The Katex library does pack the extension, and hence, we can import it as

import renderMathInElement from 'katex/dist/contrib/auto-render';
import 'katex/dist/katex.min.css';
Enter fullscreen mode Exit fullscreen mode

The imported katex.min.css controls the look & feel of the rendered equations.

Step 2.4: Create a Ref for the node that will contain the text with equations

The Katex API renderMathInElement needs a reference to the DOM node. We can use React Refs to get the reference to the DOM node that will have the text with equations.

const katexTextRef = useRef();
Enter fullscreen mode Exit fullscreen mode

Ensure that you have imported useRef from React.

Step 2.5: Add JSX for the KatexSpan element

Since we want to use this as a span element, we will keep it simple.

return (
    <div ref={katexTextRef} {...delegated}>
      {text}
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

Note that we have used the ref property to ensure that React provides a reference to this DOM node for us to use.

Step 2.6 Leverage useEffect hook to run the KaTeX Autorender renderMathInElement.

Now, that we have the reference, we can use useEffect that runs the first time after the DOM has been constructed.

useEffect(() => {
    if (katexTextRef.current) {
      renderMathInElement(katexTextRef.current, {
        delimiters: [
          { left: '$$', right: '$$', display: true },
          { left: '$', right: '$', display: false },
        ],
      });
    }
  }, []);
Enter fullscreen mode Exit fullscreen mode

Notice that we are checking if KatexTextRef has been assigned before running the auto render

Wiring it all up

'use client';
import renderMathInElement from 'katex/dist/contrib/auto-render';
import 'katex/dist/katex.min.css';
import { useEffect, useRef } from 'react';

export default function KatexSpan({ text, ...delegated }) {
  const katexTextRef = useRef();
  useEffect(() => {
    if (katexTextRef.current) {
      renderMathInElement(katexTextRef.current, {
        delimiters: [
          { left: '$$', right: '$$', display: true },
          { left: '$', right: '$', display: false },
        ],
      });
    }
  }, [text]);

  return (
    <div ref={katexTextRef} {...delegated}>
      {text}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Top comments (3)

Collapse
 
mahdimortuza profile image
Mahdi Mortuza

Thank you.
I was struggling to implement latex with nextjs.
Finally, I found that I forgot to include 'use client'.

Collapse
 
ashishworkspace profile image
Ashish Kumar

How can i do the same using typescipt

Collapse
 
mahdimortuza profile image
Mahdi Mortuza

the process is same.
you just need to install Type Definition form npm website.