Artemis
Artemis

Reputation: 599

TypeError: Cannot read property 'name' of undefined in Node js with Express

I'm using a local .json file as database for my small web appplication. It works without issues and I can retrieve data from it, but when I look to the console I see the error TypeError: Cannot read property 'name' of undefined... appearing twice each time. The error is not consistent and I can't properly replicate it and I don't understand what may cause it.

JSON

{
  "Faction1": {
    "name": "Lorem Ipsum",
    "id": "lorem-ipsum",
    "content": {
      "colors": {
        "col1": "red",
        "col2": "white",
        "col3": "grey"
      }
    }
  }
}

App.js

    //jshint esversion:6
    const express = require("express");
    const bodyParser = require('body-parser');
    const favicon = require('serve-favicon');

    const app = express();

    app.set('view engine', 'ejs');

    app.use(favicon(__dirname + '/public/favicon.ico'));

    app.use(bodyParser.urlencoded({ extended: true }));

    app.use(express.static(__dirname + '/public'));

    app.use('/scripts', express.static( __dirname + '/node_modules/'));


    const factionsDb = require(__dirname + '/views/data/factions.json');

    JSON.stringify(factionsDb);

    // -------------------------------------------------------------------------- //

    app.get('/', (req, res) => {
      res.render('pages/index', {
      pageTitle: "App Name"
      });
    });


    app.get('/factions', (req, res) => {
      res.render('pages/product-list', {
        parentPage: "'/'",
        pageTitle: "Factions",
        section: "factions",
        productsList: factionsDb
      });
    });

    app.get('/factions/:productId', (req, res) => {
      let requestedProductId = req.params.productId;

      let selectedProduct = Object.values(factionsDb).find(product => Object.values(product).includes(requestedProductId));

      res.render('pages/product-details', {
        parentPage: "'../factions'",
        pageTitle: selectedProduct.name,
        section: "factions",
        product: selectedProduct
      });
    })

    app.listen(3000, function(){
      console.log("Server started on port 3000");
    });

    // -------------------------------------------------------------------------- //

    app.use(function (req, res) {
        res.status(404).render('pages/404', {parentPage: "'/'", pageTitle: ""},
      );
    });

Upvotes: 3

Views: 4069

Answers (2)

Rise
Rise

Reputation: 1601

Need to check if there is matched item by find function.

`let selectedProduct = Object.values(factionsDb).find(product => Object.values(product).includes(requestedProductId));

If there is no matched item, it will return undefined So try to check selectedProduct.

Below I have updated pageTitle part.

  res.render('pages/product-details', {
    parentPage: "'../factions'",
    pageTitle: (selectedProduct && selectedProduct !== undefined)?  selectedProduct.name : '',
    section: "factions",
    product: selectedProduct
  });

Sync:

var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('file', 'utf8'));

Async:

var fs = require('fs');
var obj;
fs.readFile('file', 'utf8', function (err, data) {
  if (err) throw err;
  obj = JSON.parse(data);
});

Upvotes: 2

libik
libik

Reputation: 23029

If you select nonexisting product, then selectedProduct will be undefined:

let selectedProduct = Object.values(factionsDb).find(product => Object.values(product).includes(requestedProductId));

Then you try to set following pageTitle: selectedProduct.name,, which goes into selectedProduct variable and tries to find object name in it. As the selectedProduct is undefined, it throws error you mentioned.

You should be able to simulate it by calling URL with some nonssense :productId, i.e. /factions/nonexistingfaction

Upvotes: 2

Related Questions