question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Hydrated component isn't initialized in prod builds when it is exported/imported under a name different from the name of the component it decorates

See original GitHub issue

A bit cryptic title but let me explain what this is about 😃

Currently, in production mode code assumes that the name of the component that the withHydrate hook decorates and the name under which the decorated component is imported into the page are the same which is not always true.

The withHydrate hook when renders HTML stores the name of the component it decorates as a marker. The hydration code then reads the marker and tries to locate a component with this name among hydration bindings. Hydration bindings are determined based on named exports of the component file or default import names in the page component.

There are two cases when this logic fails.

A named export case:

// hydrated-component.tsx
export const HydratedComponent = withHydrate(HydratedComponentInternal);

// page.tsx
import {HydratedComponent} from './hydrated-component.tsx';

Default import case:

// hydrated-component.tsx
export default withHydrate(HydratedComponentInternal);

// page.tsx
import HydratedComponent from './hydrated-component.tsx';

In both cases in prod, the hydration code would try to locate the HydratedComponentInternal in the binding but this attempt would fail as there would be only single binding for the HydratedComponent.

Fixing this turned out to be tricky. The only fix I can think about is to parse hydration chunks, determine exported component names, and prefill a displayName parameter of the withHydrate hook with the corresponding names. This solution feels a bit hacky.

I’m wondering if you have any thoughts on what would be the right way to fix it. Take a look when you have time =)

Adding a repro below.

Steps to reproduce

  1. Checkout a named-export-fix branch in this repository.
  2. Run npm run serve
  3. Open http://localhost:8888/

Expected behavior

The page renders, HydratedComponentA and HydratedComponentB get hydrated and two alert messages are shown.

Actual behavior

The page renders but no components are hydrated because of a runtime js error.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
natemoo-recommented, Mar 22, 2021

Turns out traversing the AST was necessary to map the internal component name back to the exported name! Take a look at what I came up with in #149. Seems to be working well 😄

1reaction
nikita-grafcommented, Mar 21, 2021

That’s an interesting idea! It should work! Adding __isWithHydrate and name hoisting should be straightforward.

The most significant change that would be needed is to include inner component names into the hydrateBindings hash so that the runtime part would know a link to the file with the component that it wants to hydrate. Currently, the hydrateBindings contains exported names of the components as they appear in the source code and not the inner component names.

Maybe you see an easier way how runtime could locate a hydration chunk of an SSR rendered component?

A random idea: we could possibly add a hashed URL of the chunk next to other metadata that the withHydration renders in the SSR mode. Though, this would require modifying the AST just like in my pr linked above.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Hydration failed because the initial UI does not match ... - GitHub
I refactored the code and the error dissappeared. Can confirm refactoring worked. There were 4+ components within a single page on my code,...
Read more >
React 18: Hydration failed because the initial UI does not ...
I have been experiencing the same problem lately with NextJS and i am not sure if my observations are applicable to other libraries....
Read more >
Debugging and fixing hydration issues - somewhat abstract
So, this week, let's dig into that hydration issue with some ideas on how to debug it and how to fix it.
Read more >
Decorator - Refactoring.Guru
The Base Decorator class has a field for referencing a wrapped object. The field's type should be declared as the component interface so...
Read more >
Decorator pattern - Wikipedia
Not to be confused with the concept of "decorators" in Python. In object-oriented programming, the decorator pattern is a design pattern that allows...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found