Closed8

trpc, storybook, msw, Next.js 調査もろもろ

koga1020koga1020

1️⃣ is for mocking the client, mine is a nextjs project so by default it ends up using the trpc/next hoc, here in storybook we just use a plain react provider.

Next.jsのアプリケーションの方では trpc.withTRPC(App); としてその内部でProviderの設定をよしなにやってくれている。これに相当する処理をstorybookのdecoratorsの中でやらないとstorybook実行時にcontextの設定がなくエラーが出てしまうと。

https://github.com/trpc/trpc/blob/663c63ea80e2de267d8d4708f88c1d38a598ab6e/packages/next/src/withTRPC.tsx#L134-L139

koga1020koga1020

we just use a plain react provider

これに関しては、createTRPCNextではなくcreateTRPCReactを使ってtrpcのオブジェクト(表現が怪しい、Providerやhookを持ったオブジェクト)を作ってる的な話かな

こんな感じか?

const trpc = createTRPCReact<AppRouter>();

const trpcClient = trpc.createClient({
  // createTRPCNextに渡している設定と同じにする
  links: [...]
})
const queryClient = new QueryClient();

<trpc.Provider
  client={trpcClient}
  queryClient={queryClient}
>
  <QueryClientProvider client={queryClient}>
   </QueryClientProvider>
</trpc.Provider>
koga1020koga1020

これを組み合わせると、こんな感じでStoryに対してcontextを指定できる。これで↓↓のようなContextが設定されていないことによるエラーが出なくなる

Error: Cannot destructure property 'abortOnUnmount' of 'useContext(...)' as it is null.

https://storybook.js.org/docs/react/writing-stories/decorators#context-for-mocking

export const decorators = [
  (Story) => (
    <trpc.Provider client={trpcClient} queryClient={queryClient}>
      <QueryClientProvider client={queryClient}>
        <Story />
      </QueryClientProvider>
    </trpc.Provider>
  ),
];
koga1020koga1020

ここまではstorybook上でtrpcが動くようにする設定であり、mswは関係ない話。これでtrpcを使ってリクエストを投げている箇所が動くから、それをmockしたい→mswを使おうとなる。

koga1020koga1020

で、この辺りの記事の話になってきて、「どうhandlerを設定するよ」となる。

https://zenn.dev/takepepe/articles/trpc-msw-integration

この記事のようにやるのも手だが、↓↓のmsw-trpcを使うことで、trpcで設定したprocedureを使ってhandlerが定義できる。この書き振りが冒頭のgistで書かれている

  parameters: {
    msw: {
      handlers: [
        trpcMsw.the.query.path.for.your.schema.query((req, res, ctx) => { // :two: 
          return res(ctx.status(200), ctx.data({ id: 'trololololololol' }))
        })
      ],
    },
  },

https://github.com/maloguertin/msw-trpc/

koga1020koga1020

まとめ

  • Next.jsに対してtrpcを導入する際は trpc.withTRPC(App) でContextの設定を一括でよしなにしてくれている
  • storybookの場合に、trpcのprocedureを実行しているコンポーネントをrenderingする際に、trpc.withTRPC でwrapしていないため、useContext 周りでエラーが出る
  • storybook表示用にNext.jsではない通常のReactプロジェクト向け createTRPCReact を使って trpc.withTRPC の内部で使われているProviderが取得できる
  • このProviderを使ってStoryの設定をすれば、story内でtrpcのprocedureをエラーなく実行できる
  • trpcのprocedureが動く状態になれば、あとはいかにmockするか = mswを以下に記述するか
  • msw-trpcを入れるとmswのハンドラーの実装が楽にはなる
このスクラップは2023/04/01にクローズされました