Expand my Community achievements bar.

SOLVED

React rehydration console errors blocking on page content from Target

Avatar

Level 1

Hello! Lately we've been receiving React console errors when launching new A/B tests that we believe are related to a content mismatch during rehydration. For context, in the last test, we were trying to display a different set of headlines on a single page to see which performed better. The class names tend to change, so the elements were being targeted by unique data-attributes.

 

The React errors are:

422: There was an error while hydrating this Suspense boundary. Switched to client rendering.

418: Hydration failed because the initial UI does not match what was rendered on the server.

425: Text content does not match server-rendered HTML.

 

Example QA links for this test:

I don't see the errors 100% of the time, but more often than not. I can verify users are still being entered into each experience via console logs, but they don't see the content that corresponds to their experience - they only see the control even though they've been entered into a different experience.

 

When I changed the test from a total of four experiences to just two, the content displayed more consistently without errors. 

 

In general, the product has been really inconsistent in the past few weeks/months and other tests/QA links only work some of the time. We have tried using the bookmarklet to clear preview link cache and different browsers/devices, but that doesn't change much. Any assistance would be greatly appreciated!

 

We're eventually planning on changing to a server-side Target implementation, but that's still a work in progress.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @jsteinerkotch,

I don't know what all you want to exchange or manipulate per target in your case. Maybe it is enough to work with suppressHydrationWarning for the corresponding element.

 

If a single element’s attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the warning by adding suppressHydrationWarning={true} to the element. It only works one level deep, and is intended to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch it up, so it may remain inconsistent until future updates.

 

Or if you want to exchange more like I guess this is something that could solve your problem. But it will cause your component to be slower.

 

If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like this.state.isClient, which you can set to true in componentDidMount(). This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. Note that this approach will make your components slower because they have to render twice, so use it with caution.

https://reactjs.org/docs/react-dom.html#hydrate

 

best regards

 

 

View solution in original post

1 Reply

Avatar

Correct answer by
Community Advisor

Hi @jsteinerkotch,

I don't know what all you want to exchange or manipulate per target in your case. Maybe it is enough to work with suppressHydrationWarning for the corresponding element.

 

If a single element’s attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the warning by adding suppressHydrationWarning={true} to the element. It only works one level deep, and is intended to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch it up, so it may remain inconsistent until future updates.

 

Or if you want to exchange more like I guess this is something that could solve your problem. But it will cause your component to be slower.

 

If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like this.state.isClient, which you can set to true in componentDidMount(). This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. Note that this approach will make your components slower because they have to render twice, so use it with caution.

https://reactjs.org/docs/react-dom.html#hydrate

 

best regards