When I ran my code like this I was having errors like castError: cast to object failed for value new
app.get("/products/:id", async (req, res) => {
const { id } = req.params;
const product = await Product.findById(id);
res.render('products/show', { product });
});
app.get('/products/new', (req, res) => {
res.render("products/new");
});
but when I switched the format like this the code was running normally on my local machine.
app.get('/products/new', (req, res) => {
res.render("products/new");
});
app.get("/products/:id", async (req, res) => {
const { id } = req.params;
const product = await Product.findById(id);
res.render('products/show', { product });
});
What could be the problem is it as a result of my path params or does order count I don't understand as am just beginning to learn express.js
CodePudding user response:
app.get("/products/:id", async (req, res) => {
const { id } = req.params;
const product = await Product.findById(id);
res.render('products/show', { product });
});
app.get('/products/new', (req, res) => {
res.render("products/new");
});
In the format above, the route above the new
route includes a route parameter :id
. Express matches anything that comes after /products
as if it is the route parameter :id
that's why in the format above you got an error.
For this one, express knows that if what comes after /products/
is new
, it will run the code inside the app.get('/products/new',
callback:
app.get('/products/new', (req, res) => {
res.render("products/new");
});
app.get("/products/:id", async (req, res) => {
const { id } = req.params;
const product = await Product.findById(id);
res.render('products/show', { product });
});
CodePudding user response:
In this case order matters. If you put the route with the param first (/products/:id
), it will treat any routes that start with /products/
as a param route. Therefore, the route below will be treated as a products api call with id equal to new
.
app.get('/products/new', (req, res) => {
res.render("products/new");
});
You can fix this by putting your param route after the new route.
app.get('/products/new', (req, res) => {
res.render("products/new");
});
app.get("/products/:id", async (req, res) => {
const { id } = req.params;
const product = await Product.findById(id);
res.render('products/show', { product });
});
CodePudding user response:
The routes are evaluated in the order that they are defined, and it also doesn't what what an id
might look like.
So let's say you have a request going to /products/new
When your code looks like this:
app.get("/products/:id", async (req, res) => {
const { id } = req.params;
const product = await Product.findById(id);
res.render('products/show', { product });
});
app.get('/products/new', (req, res) => {
res.render("products/new");
});
The first route declared is "/products/:id"
, which is a match and req.params.id
will equal "new"
. Because there was a match, it will not even look at routes that were declared after it.
*edit how you could have the "/products/:id"
come first and still work the way you want, probably not the best but an example of the use case for the next
param
app.get("/products/:id", async (req, res, next) => {
const { id } = req.params;
if (id === 'new') {
next();
return; // important to remember, without it the code below will also fire
}
const product = await Product.findById(id);
res.render('products/show', { product });
});
app.get('/products/new', (req, res) => {
res.render("products/new");
});