next.js を使用して todo アプリを作成した際に、下記の点で大いに躓いた。
対象 todo を編集すべく、対象 todo
をクリックしたら todo
の id
をクエリパラメータで渡して、examle.com/editing
で編集しようとしたが、上手くいかなかった。
結論
下記でクエリパラメータを取得し、その値を元に firebase
へアクセスして、必要なデータを取得して input
の中へ表示できるようになった。
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const postId = params.get('postId')
setPostId(postId)
const getTodo = async () => {
const docRef = doc(db, "todos", postId);
await getDoc(docRef).then((doc) => {
const todo = doc.data();
setTodoContent(todo.content);
setTodoDetail(todo.detail);
});
};
getTodo();
}, []);
上手く行かなかった原因
まずは、コード。
const postId: string = typeof router.query.postId === 'string' && router.query.postId;
(async () => {
const docRef = doc(db, "todos", postId);
const docSnap = await getDoc(docRef);
const todo: any = docSnap.data();
setTodoContent(todo.content);
setTodoDetail(todo.detail);
})()
即時実行関数で、ページ遷移した時点でpostId
へクエリパラメータの値を入れて、その値を元に、 firebase
から対象のドキュメントを取得できるはずだったが、できなかった。
しかし、上記コードのトリガーをonClick
にしたら上手くいった。
なぜ上手く行かなかったのか
リロードしてrouter.query.postId
の中身を見ると分かると思うが、どうやらquery
の中身はリロードすることで空になってしまうのか、false
と出力さた。
だが、url はそのままであるため、url のクエリパラメータから取得する方法に変えた。
実装方法解説
const params = new URLSearchParams(window.location.search);
で初期化。
.get()
をつなげて、引数には返すパラメーターの名前。
それを元に、firebase
から該当のドキュメントを取得する。