remarkjs/remark-math

Next.js hydration issue

nguyenvukhang opened this issue · 9 comments

Initial checklist

Affected packages and versions

remark-math, rehype-mathjax, all latest versions

Link to runnable example

No response

Steps to reproduce

yarn create next-app
yarn add @next/mdx @mdx-js/loader @mdx-js/react remark-math rehype-mathjax

create a next.config.mjs with the contents:

import mdx from "@next/mdx";
import remarkMath from "remark-math";
import rehypeMathJax from "rehype-mathjax";

const withMDX = mdx({
  extension: /\.mdx?$/,
  options: {
    remarkPlugins: [remarkMath],
    rehypePlugins: [rehypeMathJax],
  },
});

export default withMDX({
  reactStrictMode: true,
  pageExtensions: ["tsx", "jsx", "mdx"],
});

Expected behavior

Should render without errors.

Actual behavior

Renders correctly, but with the error
Error: Text content does not match server-rendered HTML.

Runtime

Node v16

Package manager

yarn 1

OS

macOS

Build and bundle tools

Next.js (bug is seen on both v13 and v12)

This error disappears when commenting out lines 113-115 in https://github.com/remarkjs/remark-math/blob/7e82f934e77d62b7366825633bc7f1d5d5e5a861/packages/rehype-mathjax/lib/create-plugin.js

      if (found && renderer.styleSheet) {
        context.children.push(renderer.styleSheet())
      }

Though it's still unclear where the root cause is

well, the root cause is that there is different handling on the server (JSDOM) and a browser (depending on which one your users use). Not sure it can be change,d but feel free to investigate it.

I'm having this problem too. One thing I've noticed is that if you inspect a mathjax-generated element, you'll see something like this: <mjx-container classname="MathJax ...>

It should say class=, not classname= when you're inspecting in the browser. For some reason, when combined with MDX, it doesn't properly convert that attribute. If I don't use MDX and use Next.js directly, it works fine, so it has something to do with remark-math and MDX together, I think.

That seems like a very different problem? The above seems to talk about CSS, you seem to talk about (MathML) attribute conversion?

I'm not talking about MathML, at least I don't think I am.

I'm talking about how rehype-mathjax renders the HTML. Just suggesting a possible cause of the hydration error. If somehow it was being rendered as "class" on the server but "classname" on the client, I think that could cause the hydration error.

Interestingly, when I commented out the lines OP suggested, I still got the error. If I switch to rehype-katex the problem goes away.

oh sorry yeah you’re right, mjx-container is a custom element, not mathml.

when I commented out the lines OP suggested, I still got the error

Yeah, I thought it was a different problem, and this seems to indicate that.

If I switch to rehype-katex the problem goes away.

It does thing completely differently!

Can confirm this issue still exists with Next.js 14

Can confirm that this solution that avoids adding the css appears to work.

is been a while, any update or workaround for this?