Menu
CoddyTech

Nested Routes

Part of the Express Basics section of Coddy's Node.js journey. Lesson 20 of 23.

Reviews belong to one recipe, so their URLs live under it: /api/recipes/2/reviews.

const chapters = express.Router({ mergeParams: true });

chapters.get('/', (req, res) => {
    res.json(chaptersOf(req.params.isbn));
});

app.use('/api/books/:isbn/chapters', chapters);

A router's req.params holds only the parameters of its own paths. The :isbn in the mount path belongs to the app, so inside the router it is undefined, unless the router is made with mergeParams: true.

routes/reviews.js is ready, with a reviews object and a hasRecipe(id) helper.

challenge icon

Challenge

Easy

Visitors can leave reviews on a recipe. A review belongs to one recipe, so its URL sits under that recipe: /api/recipes/1/reviews.

  1. In routes/reviews.js, make the router able to read the recipe id from the path it is mounted on. Without that, req.params.id is undefined inside the router (see the lesson text).
  2. Add a GET route for /. It returns that recipe's reviews as a JSON list, or an empty list, [], when it has none yet. Keep the reviews in the reviews object, one list per recipe id, like { "1": [{ "stars": 5, "text": "Lovely" }] }.
  3. Add a POST route for /. It reads stars and text from the body, adds the review to that recipe's list, and responds with status 201 and the review: {"stars": 5, "text": "Lovely"}. Store and send only those two fields.
  4. In both routes, when hasRecipe(id) is false, respond with status 404 and {"error": "No such recipe"}.
  5. In server.js, import the router and mount it at /api/recipes/:id/reviews, next to the recipes router and before the 404 handler.

Try it: Press Run and send /api/recipes/1/reviews: []. Pick POST and send {"stars": 5, "text": "Lovely"} to /api/recipes/1/reviews: status 201 and the review. GET /api/recipes/1/reviews again: [{"stars":5,"text":"Lovely"}]. Send /api/recipes/2/reviews: still [], because each recipe keeps its own reviews. Send /api/recipes/99/reviews: status 404 and {"error":"No such recipe"}.

Try it yourself

import express from 'express';
import { recipes } from '../data.js';

// Reviews by recipe id, like { 1: [{ stars: 5, text: 'Lovely' }] }.
const reviews = {};

const hasRecipe = (id) => recipes.some((recipe) => recipe.id === Number(id));

const router = express.Router();

// GET / lists a recipe's reviews. POST / adds one.

export default router;

All lessons in Express Basics

Practice on your own: Express playground