diff --git a/src/components/application-loader/loading-screen/random-icon.tsx b/src/components/application-loader/loading-screen/random-icon.tsx index dfda67f9c..27dcb29bf 100644 --- a/src/components/application-loader/loading-screen/random-icon.tsx +++ b/src/components/application-loader/loading-screen/random-icon.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import React, { useMemo } from 'react' +import React, { useEffect, useState } from 'react' import type { IconName } from '../../common/fork-awesome/types' import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' import styles from './animations.module.scss' @@ -26,9 +26,21 @@ const elements: IconName[] = [ /** * Chooses a random fork awesome icon from a predefined set and renders it. + * + * The component uses a static icon in the first rendering and will choose the random icon after that. + * This is done because if the loading screen is prepared using SSR and then hydrated in the client, the rendered css class isn't the expected one from the SSR. (It's random. d'uh). + * To avoid this problem the icon will be chosen in an effect because SSR won't run effects. + * + * See https://nextjs.org/docs/messages/react-hydration-error */ export const RandomIcon: React.FC = () => { - const icon = useMemo(() => elements[Math.floor(Math.random() * elements.length)], []) + const [icon, setIcon] = useState() - return + useEffect(() => { + setIcon(Math.floor(Math.random() * elements.length)) + }, []) + + return icon === undefined ? null : ( + + ) }