🦔

useSWRで取得したデータを別のuseSWRで利用する

2023/01/09に公開

Environment

  • Docker 20.10.18
    • mysql:8.0.29
    • node:16.14
    • php:8.1-apache
  • Next.js v13.0.2
  • Laravel 9.38.0
  • ログイン認証:sanctum

Background

・ダッシュボード画面を表示時に、useSWRで取得したログインユーザデータを使ってuseSWRで別データを取得したい。
・ダッシュボードのURLを/idにしてuseRouterのrouter.query.idを使えば解決できそうだが、URLは/にしたかった。

Code

index.tsx
import { Typography } from '@mui/material';
import { Container, Stack } from '@mui/system';
import useSWR from 'swr';
import { BasicLoading } from '../components/atoms/Loading/BasicLoading';
import { ThreadCard } from '../components/molecules/Card/ThreadCard';
import { fetcher } from '../functions/CommonProvider';
import { ThreadInterface } from '../interfaces/Thread/ThreadInterface';

export default function Home() {
	const { data: user } = useSWR('/api/user', fetcher);
	const { data: threads } = useSWR('/api/my_thread/' + user.id, fetcher);
	if (!user || !threads) return <BasicLoading />

	return (
		<Container sx={{ mt: 2 }}>
			<Stack spacing={2} sx={{ mb: 2 }}>
				<Typography variant='h5'>My Threads</Typography>
				{threads.map((thread: ThreadInterface) => {
					return <ThreadCard thread={thread} key={thread.id} />
				})}
			</Stack>
		</Container>
	)
}

useSWR('/api/user', fetcher)でログインユーザの情報を取得し、useSWR('/api/my_thread/1',fetcher)のようにAPIを叩いてユーザのスレッド情報を取得したい。

Error

別ページからの遷移であれば問題なく表示されるが、URL直打ちやダッシュボード画面をリロードした際に以下のエラー発生。初期レンダリング時にuseSWRでuserデータが更新されないので、undefined.idとなり、プロパティにアクセスできないよ!と言われる。

Server Error
TypeError: Cannot read properties of undefined (reading 'id')

This error happened while generating the page. Any console logs will be displayed > in the terminal window.

if(user)で条件付けしようとすると、エラーになる(Hooksは条件によらずrenderingされないといけない)

Unhandled Runtime Error
Error: Rendered more hooks than during the previous render.

Solution

最終的に以下のようにfallbackDataを使用して、存在しないidを初期値として渡すことで一旦解決。

const { data: user } = useSWR('/api/user', fetcher, {
	fallbackData: { id: 0 },
});

もっといいやり方教えてください。。。

Reference

https://swr.vercel.app/docs/advanced/understanding

Discussion