前回までの作業でseRouterのrouter.queryを使ったダイナミックルーティングは出来るようになりました。(できるようになった理由は理解できていないけどね!!!!!!!)
こんな感じで、URLのクエリの文字列をページ上でレンダリングできるようになりました。ちなみにコードは以下です。
import { useRouter } from "next/router";
import React from "react";
const Page = () => {
const router = useRouter();
const id = router.query;
console.log(id.test2);
if (!router.isReady) {
return null;
}
return <p>hello! id: {id.test2}</p>;
};
export default Page;
上記のコードを書くにあたって参考にさせていただいたのはこちらの記事。
routerのisReadyプロパティを使うことで、idがundefinedになることを防いで、レンダリングできるようになりました。
これを使えば、今作っているTodoアプリの詳細ページを動的に生成できるので嬉しいです。
そして次にやりたいのは、Todoの詳細ページの中身の生成です。
今作っているTodoアプリはfirestoreを使っていて、データはすべてfirestoreのdocに格納されています。なのでfirestoreのgetメソッドを使ってデータを取得したいのですが、どのデータを取得するかを指定するのに、今回ダイナミックルーティングに使っているrouter.queryをそのまま使いたいんですよね。
そこでこんな感じで書いてみました。
import { useRouter } from "next/router";
import { db } from "../../firebase";
import React from "react";
const Page = async () => {
const router = useRouter();
const id = router.query;
console.log(id.test2);
if (!router.isReady) {
return null;
}
const TodoData = await db
.collection("tasks")
.doc("{id.test2}")
.get()
.then((snapshot) => {
console.log(snapshot.data());
return (
<>
<h1>Blog post</h1>
<p>Post id: {id.test2}</p>
</>
);
});
};
export default Page;
ですが以下のようなエラーが出てしまいました。
このエラーを翻訳してみると
エラー:オブジェクトはReactの子として有効ではありません(見つかった:[object Promise])。子のコレクションをレンダリングする場合は、代わりに配列を使用してください。
とのことです。最初はまったく意味がわかりませんでしたが、ちょっと調べてみると「asyncを使うと、Promise オブジェクトが返ってくるらしい」ということがわかりました。それはこの記事を見ていて気づきました。
なるほど・・・まそもそもね?Promiseもasync awaitもね、正直雰囲気で使っていまして。というかPromiseに関してはハジメマシテじゃないです?前にどこかでお会いした記憶はないんだよね。
ということでPromiseやasync awaitのあたりのインプットをしてみるところから始めたいと思います。
先は長そうですけど、こういう気付きが1日1個でもあるなら良しとしようと思います。