Next.js (App router) + Chakra UI で壊れた
- Next.js v14
- @chakra-ui/react v2.8.2
- @chakra-ui/next-js v2.2.0
ガイドラインに沿ってセットアップを行った
// app/providers.tsx
'use client'
import { ChakraProvider } from '@chakra-ui/react'
export function Providers({ children }: { children: React.ReactNode }) {
return <ChakraProvider>{children}</ChakraProvider>
}
// app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode,
}) {
return (
<html lang='en'>
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}
Warning: Extra attributes from the server: data-new-gr-c-s-check-loaded,data-gr-ext-installed
エラーになり何も表示されない
This is usually caused by an extension passing these extra attributes with your code when it is executed on the browser trying to interact with the UI, this creates a mismatch between what was rendered on the server and what is rendered on the client.
Extensions similar to Grammarly, ColorZilla and LanguageTool are therefore the cause of this warning, so you have to find out which one is doing this and then disable/configure it to not run on the ports you usually use for development. This is the straightforward fix for the warining, since it is always recommended to avoid extensions in development.
Chrome の拡張が HTML を変更するのが原因で dom の差分が出てしまっているのが原因
Grammarly、ColorZilla、LanguageTool といった拡張が原因らしい
<body data-new-gr-c-s-check-loaded="14.1156.0" data-gr-ext-installed="">
Grammarly が原因だった。Grammarly が body タグに付ける data-new-gr-c-s-check-loaded
data-gr-ext-installed
属性がエラーの原因。
対策 1. シークレットウィンドウを使う
拡張が無効なシークレットウィンドウならエラーは発生しない
suppressHydrationWarning={true}
属性を使う
対策 2. You can suppress hydration warnings by setting
suppressHydrationWarning
totrue
in the opening<body>
tag of the RootLayout:
cf. https://stackoverflow.com/questions/75337953/what-causes-nextjs-warning-extra-attributes-from-the-server-data-new-gr-c-s-c
// app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode,
}) {
return (
<html lang='en'>
- <body>
+ <body suppressHydrationWarning={true}>
<Providers>{children}</Providers>
</body>
</html>
)
}
必要であれあば <html>
タグにも suppressHydrationWarning={true}
を付けると良い
これで Warning: Extra attributes from the server:
のエラーは出なくなった
Chakra Provider があると deck.gl と MapLibre GL を使った地図が真っ白になる
deck.gl + MapLibre + react-map-gl を使って地図を表示させていたが、<ChakraProvider>
が親にあると真っ白になってしまう…
地図表示のコンポーネント
- deck.gl "^8.9.34"
- maplibre-gl "^4.0.2"
- react-map-gl "^7.1.7"
// /src/Map.tsx
'use client'
import { FC } from 'react';
import DeckGL from '@deck.gl/react/typed';
import * as maplibregl from 'maplibre-gl';
import { Map } from 'react-map-gl/maplibre';
import 'maplibre-gl/dist/maplibre-gl.css';
const InitialViewState = {
longitude: 16.62662018,
latitude: 49.2125578,
zoom: 4
};
const MapContainer: FC = () => {
return (
<div id='map'>
<DeckGL initialViewState={InitialViewState} controller={true}>
<Map
mapLib={maplibregl}
initialViewState={{
longitude: 16.62662018,
latitude: 49.2125578,
zoom: 3,
}}
style={{ width: '100vw', height: '100vh' }}
mapStyle='https://demotiles.maplibre.org/style.json'
>
</Map>
</DeckGL>
</div>
);
};
export { MapContainer as Map };
// app/page.tsx
import { Map } from '@/Map';
export default function Home() {
return (
<main>
<Map />
</main>
);
}
特にエラーも表示さず表示されなくなった。
use client
を外しても効果はない
ChakraProvider から Chakra UI now works with the Next 13 app router without the need to add use client directive.
https://github.com/chakra-ui/chakra-ui/issues/7649#issuecomment-1769503921
// app/providers.tsx
- 'use client'
-
import { ChakraProvider } from '@chakra-ui/react'
export function Providers({ children }: { children: React.ReactNode }) {
return <ChakraProvider>{children}</ChakraProvider>
}
ChakraProvider から use client
を取っても地図は表示されないままだった
逆に use client
を付けても効果は無かった
DeckGL の親の高さが 0 にっていたのが原因
Chakra UI の theme とバッティングしたのか、コンテナの高さが 0
になっていたために canvas の高さも 0
となち地図が表示されなくなっていただけだった
// /src/Map.tsx
import { FC } from 'react';
import DeckGL from '@deck.gl/react/typed';
import * as maplibregl from 'maplibre-gl';
import { Map } from 'react-map-gl/maplibre';
import 'maplibre-gl/dist/maplibre-gl.css';
const InitialViewState = {
longitude: 16.62662018,
latitude: 49.2125578,
zoom: 4
};
const MapContainer: FC = () => {
return (
- <div id='map'>
+ <div id='map' style={{ width: '100%', height: '100vh' }}>
<DeckGL initialViewState={InitialViewState} controller={true}>
<Map
mapLib={maplibregl}
initialViewState={{
longitude: 16.62662018,
latitude: 49.2125578,
zoom: 3,
}}
style={{ width: '100vw', height: '100vh' }}
mapStyle='https://demotiles.maplibre.org/style.json'
>
</Map>
</DeckGL>
</div>
);
};
export { MapContainer as Map };
CSS の問題だった。
これで Chakra UI のコンポーネントを 地図上に表示させられるようになった