Skip to content

Commit

Permalink
refactor, describe window < 599px issue
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-williams committed Apr 15, 2024
1 parent f3b2db7 commit e440532
Show file tree
Hide file tree
Showing 10 changed files with 1,352 additions and 146 deletions.
145 changes: 55 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
# react-data-table-hydration-bug
Repro of a hydration error ([react#418]) in [react-data-table-component]'s pagination `<nav>` element.
# [react-data-table-hydration-bug]
Repro of a [hydration error][react#418] in [react-data-table-component]'s [`Pagination` element][PaginationWrapper].

<!-- toc -->
- [Local repro](#local)
- [`pagination={false}` works fine](#no-pagination)
- [Docker repro](#docker)
<!-- /toc -->
[When the client window width][shouldShow] is < [599px][`SMALL`] or `undefined` (as during [SSR]), "rows per page" in the pagination footer [is omitted][shouldShows]. This causes a hydration error whenever the client window width is ≥599, as it is omitted on the server but rendered on the client.

## Live demo <a id="demo"></a>
[react-data-table-hydration-bug.runsascoded.com/hydration-error] was built and deployed [via Github Actions][GHA], and the error is visible in the dev console:
![][error.gif]

![](public/console-error.png)
*Hydration error iff `window.innerWidth < 599`*

Page source is [hydration-error.tsx], it's just:
## Live demo
[react-data-table-hydration-bug.runsascoded.com] was built and deployed [via GitHub Actions][GHA], and the error is visible in the dev console:

![][console-error.png]

[Page source][index.tsx]:

```tsx
import DataTable from "react-data-table-component"
import DataTable from "react-data-table-component";
import ReactMarkdown from "react-markdown";
import fs from "fs";

export function getStaticProps() {
return { props: { readme: fs.readFileSync("README.md").toString() } }
}

export default function TablePage() {
const columns = [ { name: "Str" }, { name: "Num" } ]
const data = [ { Str: "A", Num: 1 } ]
return (
const Index = ({ readme }: { readme: string }) =>
<div className={"markdown-body"}>
<ReactMarkdown>{readme}</ReactMarkdown>
<hr />
<DataTable
columns={columns}
data={data}
// This line causes a hydration error in the pagination footer "nav" element; commenting
// this line fixes it (see no-pagination-no-error.tsx)
columns={[ { name: "Str" }, { name: "Num" } ]}
data={[ { Str: "A", Num: 1 } ]}
// This line causes a hydration error in the pagination footer "nav" element (iff the
// browser window is ≥599px wide); commenting this line fixes it.
pagination
/>
)
}
</div>

export default Index
```

Error links to [react#418], console message says:
The error in the dev console links to [react#418]:
```
Uncaught Error: Minified React error #418; visit https://reactjs.org/docs/error-decoder.html?invariant=418 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
at lg (framework-5eea1a21a68cb00b.js:9:46336)
Expand All @@ -45,20 +52,20 @@ Uncaught Error: Minified React error #418; visit https://reactjs.org/docs/error-
at MessagePort.T (framework-5eea1a21a68cb00b.js:33:1894)
```

## Local repro <a id="local"></a>
Local dev mode gives more details about the error, which apparently occurs in a hierarchy like `<nav>…<span>` in [the pagination footer][PaginationWrapper]:
## Local repro
Local dev mode gives more details about the error (namely that it occurs in a hierarchy like `<nav>…<span>` in [the pagination footer][PaginationWrapper]):

```bash
git clone https://github.com/ryan-williams/react-data-table-hydration-bug && cd react-data-table-hydration-bug
pnpm install
npm run dev
```

[localhost:3000/hydration-error] *should* show something like:
[localhost:3000] will show something like:

![](public/hydration-error.png)
![][hydration-error.png]

<details><summary>Error text</summary>
Error text:

```
Unhandled Runtime Error
Expand All @@ -75,75 +82,33 @@ Expected server HTML to contain a matching <span> in <nav>.
<span>
^^^^^^
```
</details>

### Having Chrome devtools open prevents the error

Here is a screencast of an incognito showing repeated page refreshes, with and without Chrome devtools open:
Commenting out [the `pagination` property] avoids the issue; [react-data-table-component#649] and [this StackOverflow][SO] describe the same.

![](public/error.gif)

The error always occurs when devtools are closed, and never occurs when they are open.

In Safari and Firefox, and with non-dev builds, devtools doesn't seem to affect the repro.

### `pagination={false}` works fine <a id="no-pagination"></a>

[localhost:3000/no-pagination-no-error] is identical to [hydration-error.tsx] above, but [`DataTable`]'s `pagination` property is commented out, removing the error:

![](public/no-pagination-no-error.png)

`diff -u pages/hydration-error.tsx pages/no-pagination-no-error.tsx` shows:
```diff
<DataTable
columns={columns}
data={data}
- // This line causes a hydration error in the pagination footer "nav" element; commenting
- // this line fixes it (see no-pagination-no-error.tsx)
- pagination
+ // Uncommenting this line causes a hydration error in the pagination footer "nav"
+ // element (see hydration-error.tsx)
+ // pagination
/>
```

[This StackOverflow][SO] alludes to the same issue.

## Docker repro <a id="docker"></a>
Run in dev mode (in Docker):
```bash
# Build
img=react-data-table-hydration-bug
docker build -t $img .

# Run
PORT=3001
docker run --rm -it -p $PORT:3000 $img
```

As above, [localhost:3001/hydration-error] may show a hydration error, while [localhost:3001/no-pagination-no-error] will not.
[react-data-table-component]: https://github.com/jbetancur/react-data-table-component
[localhost:3000]: http://localhost:3000

This has reproduced the issue for me locally 3 of 3 attempts (re-building the Docker image using `--no-cache`).
[react#418]: https://react.dev/errors/418?invariant=418

To test a built+exported static app in Docker:
```bash
docker run -it --rm --entrypoint http-server -p $PORT:3000 $img -p 3000 out
```
As above, [localhost:3001/hydration-error] may show a hydration error, though in this case it will only appear in the browser dev-tools console, and will be minified.
[react-data-table-hydration-bug.runsascoded.com]: https://react-data-table-hydration-bug.runsascoded.com
[GHA]: https://github.com/runsascoded/react-data-table-hydration-bug/actions
[PaginationWrapper]: https://github.com/jbetancur/react-data-table-component/blob/v7.6.2/src/DataTable/Pagination.tsx#L20-L30

This form has not reproduced the issue for me locally. Analogous build+`http-server` test directly on host has exhibited the error.
[shouldShow]: https://github.com/jbetancur/react-data-table-component/blob/v7.6.2/src/DataTable/Pagination.tsx#L98
[`SMALL`]: https://github.com/jbetancur/react-data-table-component/blob/v7.6.2/src/DataTable/media.ts
[shouldShows]: https://github.com/jbetancur/react-data-table-component/blob/v7.6.2/src/DataTable/Pagination.tsx#L145-L151
[SSR]: https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering

[react-data-table-component]: https://github.com/jbetancur/react-data-table-component
[localhost:3000/hydration-error]: http://localhost:3000/hydration-error
[localhost:3000/no-pagination-no-error]: http://localhost:3000/no-pagination-no-error
[`DataTable`]: https://github.com/jbetancur/react-data-table-component/blob/v7.6.2/src/DataTable/DataTable.tsx
[SO]: https://stackoverflow.com/q/75068071
[localhost:3001/hydration-error]: http://localhost:3001/hydration-error
[localhost:3001/no-pagination-no-error]: http://localhost:3001/no-pagination-no-error
[react-data-table-component#649]: https://github.com/jbetancur/react-data-table-component/issues/649

[react#418]: https://react.dev/errors/418?invariant=418
[//]: # (gh repo links)
[index.tsx]: https://github.com/runsascoded/react-data-table-hydration-bug/blob/main/pages/index.tsx
[the `pagination` property]: https://github.com/runsascoded/react-data-table-hydration-bug/blob/main/pages/index.tsx#L17
[react-data-table-hydration-bug]: https://github.com/runsascoded/react-data-table-hydration-bug

[react-data-table-hydration-bug.runsascoded.com/hydration-error]: https://react-data-table-hydration-bug.runsascoded.com/hydration-error
[hydration-error.tsx]: pages/hydration-error.tsx
[GHA]: https://github.com/runsascoded/react-data-table-hydration-bug/actions
[PaginationWrapper]: https://github.com/jbetancur/react-data-table-component/blob/v7.6.2/src/DataTable/Pagination.tsx#L20C7-L30
[//]: # (images)
[error.gif]: error.gif
[console-error.png]: console-error.png
[hydration-error.png]: hydration-error.png
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
"dependencies": {
"next": "14.2.1",
"react": "^18",
"react-data-table-component": "^7.6.2",
"react-dom": "^18"
"react-data-table-component": "7.6.2",
"react-dom": "^18",
"react-markdown": "^9.0.1"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
1 change: 1 addition & 0 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import "@/public/github-markdown-css.css";
import type { AppProps } from "next/app";

export default function App({ Component, pageProps }: AppProps) {
Expand Down
16 changes: 0 additions & 16 deletions pages/hydration-error.tsx

This file was deleted.

38 changes: 20 additions & 18 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import Link from "next/link";
import DataTable from "react-data-table-component";
import ReactMarkdown from "react-markdown";
import fs from "fs";

export default function Index() {
const rdtc = <a target={"_blank"} href={"https://github.com/jbetancur/react-data-table-component"}>react-data-table-component</a>
const DataTable = <a href={"https://github.com/jbetancur/react-data-table-component/blob/v7.6.2/src/DataTable/DataTable.tsx"}>DataTable</a>
return (
<div>
<h1><a target={"_blank"} href={"https://github.com/runsascoded/react-data-table-hydration-bug"}>react-data-table-hydration-bug</a></h1>
<p>Repro of a hydration error in {rdtc}'s pagination <code>&lt;nav&gt;</code> element:</p>
<ul>
<li><Link href={"/hydration-error"}>/hydration-error</Link>: hydration error while rendering a simple {rdtc} {DataTable}</li>
<li><Link href={"/no-pagination-no-error"}>/no-pagination-no-error</Link>: commenting out the `pagination` property doesn't exhibit have the issue</li>
</ul>
<p>Both pages above have been compiled, so you'll have to open the dev console to see the error</p>
<p>Cloning the repo and running <code>next dev</code> allows for more context:</p>
<p><a href={"/hydration-error.png"}><img width={800} src={"/hydration-error.png"}/></a></p>
<p>See <a target={"_blank"} href={"https://github.com/runsascoded/react-data-table-hydration-bug"}>runsascoded/react-data-table-hydration-bug</a> on Github for more info.</p>
</div>
)
export function getStaticProps() {
return { props: { readme: fs.readFileSync("README.md").toString() } }
}

const Index = ({ readme }: { readme: string }) =>
<div className={"markdown-body"}>
<ReactMarkdown>{readme}</ReactMarkdown>
<hr />
<DataTable
columns={[ { name: "Str" }, { name: "Num" } ]}
data={[ { Str: "A", Num: 1 } ]}
// This line causes a hydration error in the pagination footer "nav" element (iff the
// browser window is ≥599px wide); commenting this line fixes it.
pagination
/>
</div>

export default Index
16 changes: 0 additions & 16 deletions pages/no-pagination-no-error.tsx

This file was deleted.

Loading

0 comments on commit e440532

Please sign in to comment.