Prevent react hydration error

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2022-05-09 19:12:59 +02:00
parent 197114cf18
commit 0d325b5e3b

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * 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 type { IconName } from '../../common/fork-awesome/types'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import styles from './animations.module.scss' 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. * 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 = () => { export const RandomIcon: React.FC = () => {
const icon = useMemo(() => elements[Math.floor(Math.random() * elements.length)], []) const [icon, setIcon] = useState<number | undefined>()
return <ForkAwesomeIcon icon={icon} className={styles.particle}></ForkAwesomeIcon> useEffect(() => {
setIcon(Math.floor(Math.random() * elements.length))
}, [])
return icon === undefined ? null : (
<ForkAwesomeIcon icon={elements[icon]} className={styles.particle}></ForkAwesomeIcon>
)
} }