user19666029
user19666029

Reputation:

Next JS - how to give object a unique id?

I am trying to give my object a unique id by using Math.random, but I am getting the error below. If I change the Math.random to a integer like 4, the error goes away but I need the id to be unique.

Unhandled Runtime Error

Error: Text content does not match server-rendered HTML.

See more info here: https://nextjs.org/docs/messages/react-hydration-error
const data = [
    {
        id: Math.random(),
        sentence: 'hello there',
    },
    {
        id: Math.random(),
        sentence: 'bye!',
    },
]

export default function Index(props) {
    return (
        <div>
            <h1>{data[0].id}</h1>
            <h1>{data[0].sentence}</h1>
            <h1>{data[1].id}</h1>
            <h1>{data[1].sentence}</h1>
        </div>
    )
}

Upvotes: 0

Views: 3487

Answers (3)

ivanatias
ivanatias

Reputation: 4033

As explained in my comment and one of the answers, the problem is happening because Next.js pre-renders pages, therefore, the random number generated by Math.random() when pre-rendering the page on the server doesn't match the random number generated client-side when hydration occurs.

I'm not quite sure what you're trying to achieve by setting random ids to what seems to be "dummy data" (You could do it manually with constant values that will match both server and client-side) but I understand that this might be a simplified example.

You have a couple of options, typically you'd want to move any random generation code/logic inside a useEffect hook so it executes on the client-side only.

Another solution would be to move your "dummy data" and the rendering of this data to a separate component, let's call it DummyComponent:

const data = [
    {
        id: Math.random(),
        sentence: 'hello there',
    },
    {
        id: Math.random(),
        sentence: 'bye!',
    },
]

const DummyComponent = () => (
 <>
  <h1>{data[0].id}</h1>
  <h1>{data[0].sentence</h1>
  <h1>{data[1].id}</h1>
  <h1>{data[1].sentence}</h1>
 </>
)

export default DummyComponent

And import it dynamically on your page disabling ssr:

import dynamic from 'next/dynamic'
const DummyComponent = dynamic(() => import('../components/DummyComponent'), {
  ssr: false,
})

export default function Index(props) {
  return (
    <div>
      <DummyComponent />
    </div>
   )
}

Upvotes: 1

hgb123
hgb123

Reputation: 14891

First, the page is rendered on the server, then returned to the client to rehydrate, two times initializing data would cause different ID values. This is called hydration mismatch, which is solved by useId in React 18

But using NextJS, you could solve this problem by initializing data on server to keep it consistent

export default function Index(props) {
  return (
    <div>
      <h1>{props.data[0].id}</h1>
      <h1>{props.data[0].sentence}</h1>
      <h1>{props.data[1].id}</h1>
      <h1>{props.data[1].sentence}</h1>
    </div>
  );
}

export async function getServerSideProps(context) {
  return {
    props: {
      data: [
        {
          id: Math.random(),
          sentence: 'hello there',
        },
        {
          id: Math.random(),
          sentence: 'bye!z',
        },
      ],
    }, // will be passed to the page component as props
  };
}

Stackblitz demo

References

getServerSideProps

Upvotes: 0

Andrew Kruglik
Andrew Kruglik

Reputation: 302

Use the uuid npm package to generate unique id's.

import { v4 } from "uuid";

const data = [
    {
        id: v4(),
        sentence: 'hello there',
    },
    {
        id: v4(),
        sentence: 'bye!',
    },
]

Upvotes: 0

Related Questions