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");
});
