@shopify/react-html
Version:
A component to render your react app with no static HTML.
115 lines (84 loc) • 4.84 kB
Markdown
# Migrating from `/react-html@4.x`/ `/react-serialize@1.x` to `/react-html@5.x`
The changes in this library from version 4.x to 5.x significantly changed the API. Notably, the new version takes over all the previous responsibilities of the `/react-serialize` library, and changes the API of the `HTML` component. This section summarizes the changes required to migrate.
## `<HTML />` is now `<Html />`, and is exported from `/react-html/server` instead of `/react-html`
We renamed the component from `HTML` to `Html` in order to prevent conflicts with our linting rules for pascal case components. We also moved `Html` to be a named export, rather than the default export. Finally, we exposed it through a separate `/server` entry point, which prevents server code accidentally ending up in client bundles. To migrate, update your imports and JSX references to the component.
```tsx
// before
import HTML from '@shopify/react-html/server';
const html = <HTML />;
// after
import {Html} from '@shopify/react-html/server';
const html = <Html />;
```
## `<Html />` `hideForInitialLoad` prop is gone, use `showPage()` to show the page in development
`hideForInitialLoad` was used in development to prevent a flash of unstyled contents. Because almost every project ended up doing `hideForInitialLoad={process.env.NODE_ENV === 'development'}`, we made this the default. As a result, you will need to use a bundler that can transform `process.env.NODE_ENV` for the client, and you will need to make sure to unset the hidden styling on the document. The library exposes a function you can use to do this:
```tsx
// before
// in your server middleware:
import HTML from '@shopify/react-html';
import App from '../app';
const html = (
<HTML hideForInitialLoad={process.env.NODE_ENV === 'development'}>
<App />
</HTML>
);
// in your client entrypoint:
import {hydrate} from 'react-dom';
import App from '../app';
hydrate(<App />, document.querySelector('#app'));
setTimeout(() => {
document.body.style.display = '';
}, 0);
// after
// in your server middleware:
import {Html} from '@shopify/react-html/server';
import App from '../app';
const html = (
<Html>
<App />
</Html>
);
// in your client entrypoint:
import {hydrate} from 'react-dom';
import {showPage} from '@shopify/react-html';
import App from '../app';
hydrate(<App />, document.querySelector('#app'));
showPage();
```
`showPage` is a no-op in production, so you do not need to guard this behind any checks for development.
## `<Html />` `data`/ `headData` are replaced with `bodyMarkup`/ `headMarkup`
There is no longer a first-class API for passing in serialized data to `Html`. If you were previously using `data`/ `headData`, you can use the new props and the `Serialize` component manually:
```tsx
import {Html, Serialize} from '@shopify/react-html/server';
const data = {foo: 'bar'};
const headData = {baz: 'qux'};
// before
<Html data={data} headData={headData} />
// after
<Html
headMarkup={
Object.entries(headData).map(([id, data]) => (
<Serialize key={id} id={id} data={data} />
))
}
bodyMarkup={
Object.entries(data).map(([id, data]) => (
<Serialize key={id} id={id} data={data} />
))
}
/>
```
This is obviously much more work than it was previously. We recommend that, instead of using the method, you move to the patterns described in the [app code](#app-code) section of this document. The new pattern allows you to move your serializations beside the component that actually cares about them, and automatically inserts them into the HTML document.
## `<Serializer />` is now `<Serialize />` and is exported from `/react-html/server`
The `<Serializer />` component used to be imported from `/react-serialize`. It has now moved to `/react-html/server`, and has a slightly nicer name. Note that you should only need this component during migration to the new pattern of serializations living alongside your application code.
## `getSerialized()` is now exported from `/react-html`
Similarly to `Serializer`, `getSerialized()` moved into this package, and should only be used temporarily while you move your application over the the [new patterns described above](#app-code). The function no longer returns an object with a `data` key, it simply returns the `data` directly. Finally, `getSerialized()` is now also a bit more protective; it throws if no node with a matching serialization ID is found, and it can return `undefined` if it fails to parse the JSON that was serialized.
```ts
import {getSerialized} from '@shopify/react-html';
// before
// was type {data: string}
const data = getSerialized<string>('my-data');
// after
// has type string | undefined
const data = getSerialized<string>('my-data');
```