🦔
layout.tsxに"use client"を指定したのに、そこを経由するpage.tsxでフックが使えないのはなぜ?
前提
- Geminiと壁打ちしてわかったことなので、内容は間違えているかもしれません
- 間違えていたら教えていただけると嬉しいです🙏
疑問が生まれた
前提、Next.jsにはこんな機能がある
- Next.jsには以下の機能がある
- デフォルトはサーバーサイドコンポーネントだよ
- "use client"をファイルの頭につけるとクライアントコンポーネントになるよ
- そのコンポーネントの子供にあたるコンポーネントは、"use client"をつけなくてもクライアントコンポーネントになるよ
"use client"; // これがあると、UserItemもクライアントコンポーネントとする
import { UserItem } from "../_components/UserItem";
export default function UsersPage() {
return (
<div>
<UserItem />
</div>
);
}
ということは?
- ってことはlayout.tsxとpage.tsxも同じ話だよね
- 同じディレクトリ内にlayout.tsxとpage.tsxがある場合
- layout.tsxをクライアントコンポーネントにすれば、page.tsxもクライアントコンポーネントになるから、useEffectとか使えるよね
- 同じディレクトリ内にlayout.tsxとpage.tsxがある場合
結果
useEffect使えない。エラーになった。なんでや。
Geminiと壁打ちしてわかったことまとめ
訳わからなすぎて1時間くらい壁打ちしてた。
結論わかったこと。
なぜlayout.tsxに"use client"を指定してもエラーになるのか
- 結論、page.tsxに"use client"がないと、ビルド時にサーバーコンポーネントと認識される
- なのでuseEffectとかでエラーになる
図にするとこんな感じ
つまり、page.tsxは普通にサーバーサイドコンポーネントとして処理されたのち、出来上がった結果がアントコンポーネントであるlayout.tsxの子要素に挿入される。
layout.tsxの子がpage.tsxであるという解釈が間違えていた
- page.tsxは単体でビルドされる
- デフォルトはサーバーコンポーネント、use clientが指定されていればクライアントコンポーネントとして扱われる
- その処理結果が、layout.tsxに渡る
→ なので、layout.tsxがクライアントコンポーネントだからといって、その下部でレンダリングされる予定のpage.tsxもクライアントコンポーネントになるわけではない。
- page.tsxでuseEffectなどをを使いたい場合
- 経由するlayout.tsxに"use client"があっても、page.tsxに記述がないとビルドエラー
- ビルド時のチェックを抜けるためにpage.tsxにも"use client"を書く必要ある
感想
頭おかしくなりそうだった🚗
Discussion