fix: fixed hydration errors by setting ids

moved scripts to body since beforeInteractive strategy ones will be placed in the head regardless, avoiding double render
This commit is contained in:
Christian Andolf
2025-06-30 13:28:05 +02:00
parent a0b0ed2544
commit 18cbd952b7
4 changed files with 42 additions and 29 deletions

View File

@@ -49,15 +49,6 @@ export default async function RootLayout(
<FontPreload /> <FontPreload />
<AdobeSDKScript /> <AdobeSDKScript />
<GTMScript /> <GTMScript />
<Script
strategy="beforeInteractive"
data-blockingmode="auto"
data-cbid="6d539de8-3e67-4f0f-a0df-8cef9070f712"
data-culture={params.lang}
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
async={true}
/>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<Script id="ensure-adobeDataLayer">{` <Script id="ensure-adobeDataLayer">{`
window.adobeDataLayer = window.adobeDataLayer || [] window.adobeDataLayer = window.adobeDataLayer || []
@@ -90,6 +81,16 @@ export default async function RootLayout(
</ClientIntlProvider> </ClientIntlProvider>
</SessionProvider> </SessionProvider>
</div> </div>
<Script
strategy="beforeInteractive"
data-blockingmode="auto"
data-cbid="6d539de8-3e67-4f0f-a0df-8cef9070f712"
data-culture={params.lang}
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
async={true}
/>
</body> </body>
</html> </html>
) )

View File

@@ -39,14 +39,6 @@ export default async function RootLayout(
<head> <head>
<AdobeSDKScript /> <AdobeSDKScript />
<GTMScript /> <GTMScript />
<Script
strategy="beforeInteractive"
data-blockingmode="auto"
data-cbid="6d539de8-3e67-4f0f-a0df-8cef9070f712"
data-culture={params.lang}
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
/>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<Script id="ensure-adobeDataLayer">{` <Script id="ensure-adobeDataLayer">{`
window.adobeDataLayer = window.adobeDataLayer || [] window.adobeDataLayer = window.adobeDataLayer || []
@@ -71,6 +63,15 @@ export default async function RootLayout(
</TrpcProvider> </TrpcProvider>
</ClientIntlProvider> </ClientIntlProvider>
</SessionProvider> </SessionProvider>
<Script
strategy="beforeInteractive"
data-blockingmode="auto"
data-cbid="6d539de8-3e67-4f0f-a0df-8cef9070f712"
data-culture={params.lang}
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
/>
</body> </body>
</html> </html>
) )

View File

@@ -41,15 +41,6 @@ export default async function RootLayout(
<FontPreload /> <FontPreload />
<AdobeSDKScript /> <AdobeSDKScript />
<GTMScript /> <GTMScript />
<Script
strategy="beforeInteractive"
data-blockingmode="auto"
data-cbid="6d539de8-3e67-4f0f-a0df-8cef9070f712"
data-culture={params.lang}
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
async={true}
/>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<Script id="ensure-adobeDataLayer">{` <Script id="ensure-adobeDataLayer">{`
window.adobeDataLayer = window.adobeDataLayer || [] window.adobeDataLayer = window.adobeDataLayer || []
@@ -71,6 +62,16 @@ export default async function RootLayout(
<ReactQueryDevtools initialIsOpen={false} /> <ReactQueryDevtools initialIsOpen={false} />
</TrpcProvider> </TrpcProvider>
</ClientIntlProvider> </ClientIntlProvider>
<Script
strategy="beforeInteractive"
data-blockingmode="auto"
data-cbid="6d539de8-3e67-4f0f-a0df-8cef9070f712"
data-culture={params.lang}
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
async={true}
/>
</body> </body>
</html> </html>
) )

View File

@@ -2,7 +2,7 @@
import { cva } from "class-variance-authority" import { cva } from "class-variance-authority"
import Downshift from "downshift" import Downshift from "downshift"
import { type ChangeEvent, type FormEvent } from "react" import { type ChangeEvent, type FormEvent, useId } from "react"
import { useFormContext, useWatch } from "react-hook-form" import { useFormContext, useWatch } from "react-hook-form"
import { useIntl } from "react-intl" import { useIntl } from "react-intl"
@@ -46,6 +46,7 @@ export function Search({
}: SearchProps) { }: SearchProps) {
const { register, setValue, setFocus } = useFormContext() const { register, setValue, setFocus } = useFormContext()
const intl = useIntl() const intl = useIntl()
const searchLabelId = useId()
const searchTerm = useWatch({ name: SEARCH_TERM_NAME }) as string const searchTerm = useWatch({ name: SEARCH_TERM_NAME }) as string
const { searchHistory, insertSearchHistoryItem, clearHistory } = const { searchHistory, insertSearchHistoryItem, clearHistory } =
useSearchHistory() useSearchHistory()
@@ -117,7 +118,10 @@ export function Search({
<div className={searchContainerVariants({ variant })}> <div className={searchContainerVariants({ variant })}>
<div className={styles.inputContainer}> <div className={styles.inputContainer}>
<label <label
{...getLabelProps({ htmlFor: SEARCH_TERM_NAME })} {...getLabelProps({
htmlFor: SEARCH_TERM_NAME,
id: searchLabelId,
})}
className={labelVariants({ className={labelVariants({
color: withSearchButton && isOpen ? "default" : "red", color: withSearchButton && isOpen ? "default" : "red",
})} })}
@@ -127,11 +131,17 @@ export function Search({
{intl.formatMessage({ defaultMessage: "Where to?" })} {intl.formatMessage({ defaultMessage: "Where to?" })}
</span> </span>
</Typography> </Typography>
<div {...getRootProps({}, { suppressRefError: true })}> <div
{...getRootProps(
{ "aria-labelledby": searchLabelId },
{ suppressRefError: true }
)}
>
<div className={searchInputClassName}> <div className={searchInputClassName}>
<Input <Input
{...getInputProps({ {...getInputProps({
id: SEARCH_TERM_NAME, id: SEARCH_TERM_NAME,
"aria-labelledby": searchLabelId,
onFocus() { onFocus() {
openMenu() openMenu()
}, },