Next.js server prop did not match client prop; And conditional style/class rendering
Tags: nextjs, tailwindcss, css, react
Published: 2023-09-11 22:01:11

Have you ever gotten the enigmatic Next.js error: "Warning: Prop "{your-prop}" did not match. Server: "{value-1}" Client: "{value-2}"?

Here is the fun fact, conditional rendering did not cause this error. But at the beginning I thought it did, that's why I created this post, so everyone struggling to get rid of that error can understand why it happens, and how to solve it.

Here is our example:
``` typescript
type TGrid = (0 | 1)[][];

const generateRandomTiles = () => {
  const grid: TGrid = [];
  for (let i = 0; i < numRows; i++) {
    grid.push(Array.from(Array(numCols), () => (Math.random() > 0.7 ? 1 : 0))); // returns a live cell 70% of the time
  }
  return grid;
};

export const Game = () => {
  const [grid, setGrid] = useState<TGrid>(generateRandomTiles());

  return (
    grid?.map((rows, i) =>
      rows.map((col, k) => {
          return (
            <div
              // classNames is a library that combines class texts. But this can be thought as "w-4 h-4 border-solid border border-gray-400" + grid[i][k] ? "bg-pink-400" : "bg-white"
              className={classNames(
              "w-4 h-4 border-solid border border-gray-400",
              grid[i][k] ? "bg-pink-400" : "bg-white"
              )}
              key={`${i}-${k}`}
            />
          )
      })
    )
  );
};

```
This code causes the following error to fire:
> Warning: Prop `className` did not match. Server: "w-4 h-4 border-solid border border-gray-400 bg-white" Client: "w-4 h-4 border-solid border border-gray-400 bg-pink-400"

So I thought it happened because I conditionally rendered `bg-pink-400` and `bg-white`. But it wasn't, the real problem is a little more sneaky than that.

## Do not generate values when defining useState.

The real culprit is this the line where we define our grid state:
`const [grid, setGrid] = useState<TGrid>(generateRandomTiles());`

The problem here is that Next.js has certain state in mind when we generate the tiles in the server, but when the client runs hydrates, we end up with a different random array when we generateRandomTiles() in the frontend. You can notice this if you console log grid, and check your next.js terminal log and your frontend log.

> There is a great article by react.gg about this: https://ui.dev/c/react/effects?ck_subscriber_id=2248853627

## How do we fix it?

Simple, we manage effects on the frontend. Like this:

``` Typescript

const [grid, setGrid] = useState<TGrid>();

  useEffect(() => {
    const initialGrid = generateRandomTiles();
    // Comment, first refresh
    setGrid(initialGrid);
  }, []);

```

Now we will not have a mismatch between frontend and backend style rendering, and the error will not happen anymore.

## Useful links if you want to go deeper:
* https://stackoverflow.com/questions/70093133/add-dynamic-tailwind-class-to-a-react-component-next-js-tailwind-ts
* https://stackoverflow.com/questions/69523463/nextjs-not-render-as-expected-and-throw-warning-prop-style-did-not-match-wh
* https://github.com/tailwindlabs/tailwindcss/discussions/3461