3秒でわかる
Express で URL のパスに埋め込んだ値を受け取るオブジェクト。/users/3 の 3 のような、リソースを名指しする部分を取り出します。
もう少し詳しく
どういうものか
req.params は Express のルーティングで、パスの中に置いたパラメータへ実際に入ってきた値をまとめたオブジェクトです。
ルート定義 /users/:id
<a href="/glossary/http-request" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">リクエスト</a> /users/42
req.params { id: '42' }パラメータは複数置けます。投稿とコメントを両方受け取るルートなら、req.params は 2 つのキーを持ちます。値は常に文字列です。
なぜ必要か
REST の考え方では、どのリソースを扱うかは URL のパスで表します。1 件のユーザーを取りたいなら /users/42 であって、/users?id=42 ではありません。この「パスに埋め込まれた識別子」をサーバー側で受け取る唯一の入口が req.params です。ここを使わないと、ユーザーごとに別のルートを書くことになってしまいます。
具体例
const express = require("express");
const app = express();
app.get("/users/:id", (req, res) => {
const id = Number(req.params.id);
if (Number.isNaN(id)) {
return res.status(400).json({ error: "id must be a number" });
}
const user = users.find((u) => u.id === id);
if (!user) return res.status(404).json({ error: "not found" });
res.json(user);
});
app.get("/posts/:postId/comments/:commentId", (req, res) => {
console.log(req.params); // { postId: '7', commentId: '3' }
res.json({ ...req.params });
});Number() を挟んでいるのが要点です。req.params.id は "42" という文字列なので、u.id === req.params.id は数値の id と一致せず、常に見つからないという結果になります。
つまずきやすいところ
最も多いのは、この文字列と数値の取り違えです。データベースを使っていると型が緩く吸収されて動いてしまう場合があり、配列やオブジェクトを直接扱うときだけ壊れるので原因が見えにくくなります。
次に多いのが、ルートの定義順による取り違えです。パラメータを含むルートを先に書くと、/users/new へのリクエストが id が new のものとして先に一致してしまいます。固定の文字列を含むルートを先に、パラメータを含むルートを後に書きます。
router を分けている場合、親のパラメータは既定では子に渡りません。Router を作るときに mergeParams を true にして初めて、req.params に親の値が入ります。
似た用語との違い
| 取得元 | どこの値か | 例 |
|---|---|---|
req.params | パスに埋め込んだ値 | /users/42 の 42 |
req.query | ? 以降の検索条件 | /users?page=2 の 2 |
req.body | リクエスト本文 | POST で送る JSON |
覚え方
params は「どれを」、query は「どう絞るか」、body は「何を送るか」。3 つの入口を役割で分けて覚えます。