StorybookでuseRouter()を使ったらエラーが出た!
はじめに
Storybookを使用していたらエラーが発生したので、どうしてそのエラーが出たのか調べてみて、対応を書きました🙌
Storybookとは
こちらに'Storybookは「UIカタログ」です。それぞれのUIコンポーネントをブラウザで手軽にチェックすることができます。'と書いてありました!
とてもわかりやすく書いてあるので、ご覧ください!
公式も貼っておきます。コード解説
Storybookで、Headerコンポーネントを表示しようとしました。
import { Header } from '.';
export const Story = () => (
<>
<Header />
</>
);
export default {
title: 'components/Header',
component: Header,
tags: ['autodocs'],
};
export defaultとは?
Storybookにコンポーネントを認識させる記述。
tags: ['autodocs']とは?
コンポーネントのドキュメントを自動生成するコード。
エラー内容
Storybookで、Headerコンポーネントを表示しようとした際に、下記のエラーが発生しました。
Error
Error: invariant expected app router to be mounted
訳: 不変条件はがapp routerがマウントされることを期待している
App Routerが適切にマウントされていないということだと思います!
App Routerとは?
src/app配下にフォルダやファイルを置く事で、ルーティングできます。
マウントとは?
DOMツリーに要素を追加していくこと。簡単にいえば、該当のReactコンポーネントを画面に表示するために最初に行われる処理のこと。
ツリーから要素を削除していくことをアンマウントという。
対応
<Header />内でuseRouter()を使用して、ページ遷移をする処理を書いていたのでそれが原因だと思います。
下記のように書いたら直りました。
import { Header } from '.';
export const Story = () => (
<>
<Header />
</>
);
export default {
title: 'components/Mypage/Header',
component: Header,
//ここを追加
parameters: {
nextjs: {
appDirectory: true,
},
},
tags: ['autodocs'],
};
こちらのコメントを参考にして書きました!
useRouter()とは?
ルーティングに関連する機能をコンポーネント内で利用するためのもの
parametersとは?
ストーリーの振る舞いをカスタマイズするために追加される設定
appDirectory: trueとは?
公式にはこのように書いてありました。
If your story imports components that use next/navigation, you need to set the parameter nextjs.appDirectory to true in for that component's stories:
訳: ストーリーがnext/navigationを使用するコンポーネントをインポートする場合、そのコンポーネントのストーリーでパラメータnextjs.appDirectoryをtrueに設定する必要があります。
If your Next.js project uses the app directory for every page (in other words, it does not have a pages directory), you can set the parameter nextjs.appDirectory to true in the .storybook/preview.js|ts file to apply it to all stories.
訳: Next.jsプロジェクトがすべてのページにappディレクトリを使用する場合(言い換えれば、pagesディレクトリを持たない場合)、.storybook/preview.js|tsファイルでnextjs.appDirectoryパラメータをtrueに設定すると、すべてのストーリーに適用されます。
つまり、appDirectory: trueは、app routerを適応させるためのものだと思います!
appDirectory: trueは、App Routerを適応させるためのものということは、Page Routerの時のuseRouter()を使用する時にはつけなくても大丈夫なのか?とか気になりましたが、そこら辺は今回は省略し、別記事に余裕があれば書こうと思います!
まとめ
今回は、Storybookでinvariant expected app router to be mountedのエラーが発生した原因について調べてみました!
コンポーネント内で、useRouter()などのページ遷移の処理を行う時は、parameterにnextjsのappDirectory: true,を記述したらStorybookがApp Routerに適応されるということが分かりました!
同じエラーに直面した方の参考になると嬉しいです!
Discussion