useSWRで取得したデータを別のuseSWRで利用する
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
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
Discussion