hydration issue
Unanswered
Shaurya posted this in #help-forum
ShauryaOP
https://srcb.in/31gdFt4Hr6
I've made a loading screen, it works perfect as I want but I get an error:
I've made a loading screen, it works perfect as I want but I get an error:
Warning: Prop `style` did not match. Server: "animation-duration:0.7999999999999999s" Client: "animation-duration:0.4s"
at div
at div
at div
at Loadingwhat could I doto fix that issue?30 Replies
can i see the code where you used animation-duration?
there I set the animation-duration to the div
ShauryaOP
yeah
return lines.map(line => line) sounds redundant
why not just return lines
what i meant by useState is
const [mounted, setMounted] = useState(false)
useEffect(()=> {setMounted(true)}, [])
return ( mounted ? children : <></> )but im not sure again
@aardani return lines.map(line => line) sounds redundant
ShauryaOP
oh, yea, did that, forgot it's already an array
ShauryaOP
this is the updated code with the mounted method: https://srcb.in/WTTuPtV127
it gets rid of the error. like it takes some time to mount and in that time the screen in blank and when it's mounted the loader is shown for very less time, I could increase the duration of the loader but the blank screen before the mount would be still there.
but I want the loading screen to show up immediately, what do I do to fix it?
it gets rid of the error. like it takes some time to mount and in that time the screen in blank and when it's mounted the loader is shown for very less time, I could increase the duration of the loader but the blank screen before the mount would be still there.
but I want the loading screen to show up immediately, what do I do to fix it?
the error is due to getUniqueRandomFromArr() i think, the random prerendered on the server is not the same as the random prerendered on the client
@joulev the error is due to getUniqueRandomFromArr() i think, the random prerendered on the server is not the same as the random prerendered on the client
ShauryaOP
hmm, what could I do for fixing it?
this is the function, gets a unique random element from an array
this is the function, gets a unique random element from an array
export function getUniqueRandomFromArr<T>(arr: T[]): T {
const random = getRandomFromArr(arr)
arr.splice(arr.indexOf(random), 1)
return random
}@Shaurya hmm, what could I do for fixing it?
this is the function, gets a unique random element from an arrayts
export function getUniqueRandomFromArr<T>(arr: T[]): T {
const random = getRandomFromArr(arr)
arr.splice(arr.indexOf(random), 1)
return random
}
make a server component that generates a random value during runtime (on the edge for perf), pass that random value to this function as seed
@joulev make a server component that generates a random value during runtime (on the edge for perf), pass that random value to this function as seed
ShauryaOP
oh, lemme do that, so I won't have to use the mounting method there right
no need
@joulev no need
ShauryaOP
can you give me the docs on Server Component to pass data to Client Components or some tutorial, haven't ever used server components in nextjs and just tried many things but I did it wrong
"use server"
import { generateRange, getUniqueRandomFromArr } from "@/lib/utils/array"
import styles from "@/styles/utils/Loading.module.css"
export default async function Lines() {
const numberOfLines = 5
const min = 0.3
const step = 0.1
const max = min + step * numberOfLines
const durations = generateRange(min, max, step)
const lines = []
for (let i = 0; i < numberOfLines; i++) {
const duration = getUniqueRandomFromArr(durations)
const formattedDuration = duration.toFixed(1)
lines.push(
<div
key={i}
className={styles.line}
style={{ animationDuration: `${formattedDuration}s` }}
/>
)
}
return <div className={styles.lines}>{lines}</div>
}"use client"
import { useEffect } from "react"
import Lines from "@/lib/actions/utils/loading"
import styles from "@/styles/utils/Loading.module.css"
const numberOfLines = 5
export default function Loading() {
useEffect(() => {
const loader = document.getElementById("loader") as HTMLElement
if (!loader) return
setTimeout(() => {
loader.style.opacity = "0"
setTimeout(() => {
loader.style.display = "none"
}, 300)
}, 100)
}, [])
return (
<div id="loader" className={styles.loader}>
<Lines />
</div>
)
}export default function Loading() {
const randomNumber = getRandomNumber();
return <LoadingClient seed={randomNumber} />;
}"use client";
export default function LoadingClient({ seed }) {
const randomArray = getRandomArrayFromSeed(seed);
return <div>...</div>;
}@joulev ts
export default function Loading() {
const randomNumber = getRandomNumber();
return <LoadingClient seed={randomNumber} />;
}
ts
"use client";
export default function LoadingClient({ seed }) {
const randomArray = getRandomArrayFromSeed(seed);
return <div>...</div>;
}
ShauryaOP
didn't understand how would that actually work and how would I implement it in mine
I did this:
I did this:
@/lib/actions/utils/loading: "use client"
import { useEffect } from "react"
import { getUniqueRandomFromArr } from "@/lib/utils/array"
import styles from "@/styles/utils/Loading.module.css"
export default function Lines({ durations }: { durations: number[] }) {
const numberOfLines = 5
useEffect(() => {
const loader = document.getElementById("loader")
if (!loader) return
setTimeout(() => {
loader.style.opacity = "0"
setTimeout(() => {
loader.style.display = "none"
}, 300)
}, 100)
}, [])
function renderLines() {
const lines = []
for (let i = 0; i < numberOfLines; i++) {
const duration = getUniqueRandomFromArr(durations)
lines.push(<div key={i} className={styles.line} style={{ animationDuration: `${duration}s` }} />)
}
return lines
}
return (
<div id="loader" className={styles.loader}>
<div className={styles.lines}>{renderLines()}</div>
</div>
)
}Loading.tsx: import Lines from "@/lib/actions/utils/loading"
import { generateRange } from "@/lib/utils/array"
import styles from "@/styles/utils/Loading.module.css"
const numberOfLines = 5
export default function Loading() {
const min = 0.3
const step = 0.1
const max = min + step * numberOfLines
const durations = generateRange(min, max, step)
return (
<div id="loader" className={styles.loader}>
<Lines durations={durations} />
</div>
)
}ShauryaOP
I just deployed it to vercel https://loader-self.vercel.app/ and in production the error doesn't come
but in dev environment why is that error coming?
but in dev environment why is that error coming?
i'm having a different problem elsewhere that requires my full attention, could you wait until later today
ShauryaOP
sure, no problem, the error only comes in the dev environment and not in the production environement and it works perfect, but that error on the console confused me because I don't see anything wrong
import { getUniqueRandomFromArr } from "@/lib/utils/array";
import styles from "@/styles/utils/Loading.module.css";
import AnimateLoader from "./animate-loader";
export default function Lines({ durations }: { durations: number[] }) {
const numberOfLines = 5;
function renderLines() {
const lines = [];
for (let i = 0; i < numberOfLines; i++) {
const duration = getUniqueRandomFromArr(durations);
lines.push(
<div
key={i}
className={styles.line}
style={{ animationDuration: `${duration}s` }}
/>
);
}
return lines;
}
return (
<div id="loader" className={styles.loader}>
<div className={styles.lines}>{renderLines()}</div>
<AnimateLoader />
</div>
);
}"use client";
import { useEffect } from "react";
export default function AnimateLoader() {
useEffect(() => {
const loader = document.getElementById("loader");
if (!loader) return;
setTimeout(() => {
loader.style.opacity = "0";
setTimeout(() => {
loader.style.display = "none";
}, 300);
}, 100);
}, []);
return null;
}