17

I'm building a next.js app that generates some random numbers which generates the warning:

Warning: Text content did not match. Server: "1" Client: "2"

I think I understand why I get this warning (the virtual DOM is kinda-sorta-out-of-sync with what was sent from the server). I'm just wondering if there's a way to let next.js/React know that this is ok in this situation. Or is there a way to only generate the random on the server and let the client use this as a literal?

Or should I just ignore the warning?

Koen
  • 3,626
  • 1
  • 34
  • 55

3 Answers3

11

Moving JavaScript random variable into React state solved the problem for me.

Here's my problem (simplified) before:

function RandomNumber() {
  const randomNumber = Math.floor(Math.random() * 100);
  return <p>{randomNumber}</p>;
}

After

function RandomNumber() {
  const [randomNumber, setRandomNumber] = useState(undefined);

  useEffect(() => {
    setRandomNumber(Math.floor(Math.random() * 100));
  }, []);

  return <p>{randomNumber}</p>;
}

My code used React Hooks useState and useEffect, but previous React lifecycle methods setState and componentDidMount should work fine too

zenoh
  • 2,071
  • 1
  • 22
  • 38
1

What I would suggest is that you wrap the content that you have some random generated content in, inside a component.

components/NoSsr.js

import dynamic from 'next/dynamic';
import React from 'react';

const NoSsr = ({ children }) => <>{children}</>;

export default dynamic(() => Promise.resolve(NoSsr), {
  ssr: false,
});

And then in your file:

<NoSsr>
    { Math.random() }
</NoSsr>
FooBar
  • 5,752
  • 10
  • 44
  • 93
0

I would do it with useMemo:

 const randomNumber = useMemo(() => Math.floor(Math.random() * 100), []);
Jöcker
  • 5,281
  • 2
  • 38
  • 44
  • I'm doing this multiple times in a row on the server. I guess this code would give me the same number each time? – Koen Oct 06 '22 at 12:11
  • Depends on what you write in the dependency array. You can create an array of random numbers that gets updated ones your rows state update. – Jöcker Oct 06 '22 at 13:48
  • This does not solve the hydration issue. The problem is not memoization, it's the fact that the content pre-generated on the server does not match the content generated during hydration on the client-side. Forcing the random number to only be generated on the client is the solution (like the other answers mentioned). – juliomalves Oct 10 '22 at 22:37
  • I have similar problem with Array random, I tried memoizing, but that doesn't work for server. When I consoled inside memo with no deps, it consoled 4 times on server for me. Which is strange, as it shouldn't happen. – Lost Stranger Dec 22 '22 at 13:36