So i’ve this component RandomShape that should return a random svg component from the list on every reload, but it causes hydration error on the client side
import React from "react";
import shapes, { getRandomShape } from "./icons";
function RandomShape (options) {
if (options.random){
const randomShape = getRandomShape(shapeType);
shapeType = shapeType || randomShape.type;
shapeIndex = randomShape.index;
}
const Shape = shapes[shapeType][shapeIndex]; // the jsx component mapped from object
return <Shape {...options} />;
};
export default RandomShape;
//./icons/index.tsx
import Star1 from "./stars/s_1";
import Star2 from "./stars/s_2";
const shapes = {
star: [Star1, Star2],
// ... other shapes
};
export const getRandomShape = (shapeType: keyof typeof shapes) => {
const keys = Object.keys(shapes);
const type = shapeType || keys[ Math.floor(keys.length * Math.random())];
const index = Math.floor(shapes[type].length * Math.random());
return {
type,
index
};
};
export default shapes;
'use client'
import RandomShape from './randomShape.jsx';
export default function Header(){
return(
<RandomShape />
);
};
The errors i’m getting
Error: Hydration failed because the initial UI does not match what was rendered on the server.
Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
I’ve tried waiting until the component is mounted but it didn’t work.
function RandomShape (options) {
let shapeType = options.type
let shapeIndex = options.index
const [Shape, setRenderedShape] = useState(null);
useEffect(()=>{
if (options.random || !(shapeType && shapeIndex)){
const randomShape = getRandomShape(shapeType);
shapeType = shapeType || randomShape.type;
shapeIndex = randomShape.index;
}
const shape = shapes[shapeType][shapeIndex];
setRenderedShape(shape);
},[])
if (!Shape) {
return null;
}
return <Shape {...options} />;
};
The component should change on every reload but its only changes for few millisecs and goes back to initial one causing hydration Error. How do i solve it?
>Solution :
The hydration error you’re encountering typically occurs when the initial server-rendered HTML doesn’t match the HTML produced by the client. In your case, it seems like the mismatch is happening because the server-rendered HTML and the client-rendered HTML are different due to the randomness in selecting the shape.
To resolve this issue, you need to ensure that the same random shape is selected on the server and the client. Here’s a revised version of your RandomShape component that should address the hydration error:
import React, { useState, useEffect } from "react";
import shapes, { getRandomShape } from "./icons";
function RandomShape(options) {
const [shapeType, setShapeType] = useState(null);
const [shapeIndex, setShapeIndex] = useState(null);
useEffect(() => {
if (options.random || !(shapeType && shapeIndex)) {
const randomShape = getRandomShape(options.type);
setShapeType(randomShape.type);
setShapeIndex(randomShape.index);
}
}, []);
if (!shapeType || !shapeIndex) {
return null;
}
const Shape = shapes[shapeType][shapeIndex];
return <Shape {...options} />;
}
export default RandomShape;
With this change, the RandomShape component now sets the shapeType and shapeIndex states on both the server and the client, ensuring that the same random shape is selected during server-side rendering and client-side rendering. This should prevent the hydration error you were encountering.