Niccolo Bianchi
Niccolo Bianchi

Reputation: 21

TypeError: Cannot read properties of undefined (reading 'forEach')

So... I've been creating this website from scratch and now i'm integrating it with prismic but i keep getting this error in the terminal: TypeError: Cannot read properties of undefined (reading 'forEach').

The consequence of this error is that the local version of this website doesn't seem to load at all.

I don't really know what is wrong with my code so i'll leave it down for you to check.

require('dotenv').config();

const fetch = require('node-fetch');
const path = require('path');
const express = require('express');

const app = express();
const port = process.env.PORT || 8005;

const Prismic = require('@prismicio/client');
const PrismicH = require('@prismicio/helpers');

// Initialize the prismic.io api
const initApi = (req) => {
  return Prismic.createClient(process.env.PRISMIC_ENDPOINT, {
    accessToken: process.env.PRISMIC_ACCESS_TOKEN,
    req,
    fetch,
  });
};

// Link Resolver
const HandleLinkResolver = (doc) => {
  // Define the url depending on the document type
  //   if (doc.type === 'page') {
  //     return '/page/' + doc.uid;
  //   } else if (doc.type === 'blog_post') {
  //     return '/blog/' + doc.uid;
  //   }

  // Default to homepage
  return '/';
};

// Middleware to inject prismic context
app.use((req, res, next) => {
  res.locals.ctx = {
    endpoint: process.env.PRISMIC_ENDPOINT,
    linkResolver: HandleLinkResolver,
  };
  res.locals.PrismicH = PrismicH;

  next();
});

app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));
app.locals.basedir = app.get('views');

const handleRequest = async (api) => {
  const [meta, home, about, { results: collection }] = await Promise.all([
    api.getSingle('meta'),
    api.getSingle('home'),
    api.getSingle('about'),
    api.query(Prismic.Predicates.at('document.type', 'collection'), {
      fetchLinks: 'product.image',
    }),
  ]);

  const assets = [];

  home.data.gallery.forEach((item) => {
    assets.push(item.image.url);
  });

  about.data.gallery.forEach((item) => {
    assets.push(item.image.url);
  });

  about.data.body.forEach((section) => {
    if (section.slice_type === 'gallery') {
      section.items.forEach((item) => {
        assets.push(item.image.url);
      });
    }
  });

  collection.forEach((collection) => {
    collection.data.products.forEach((item) => {
      assets.push(item.products_product.data.image.url);
    });
  });

  return {
    assets,
    meta,
    home,
    collections,
    about,
  };
};

app.get('/', async (req, res) => {
  const api = await initApi(req);
  const defaults = await handleRequest(api);

  res.render('pages/home', {
    ...defaults,
  });
});

app.get('/about', async (req, res) => {
  const api = await initApi(req);
  const defaults = await handleRequest(api);

  res.render('pages/about', {
    ...defaults,
  });
});

app.get('/collection', async (req, res) => {
  const api = await initApi(req);
  const defaults = await handleRequest(api);

  res.render('pages/collection', {
    ...defaults,
  });
});

app.get('/detail/:uid', async (req, res) => {
  const api = await initApi(req);
  const defaults = await handleRequest(api);

  const product = await api.getByUID('product', req.params.uid, {
    fetchLinks: 'collection.title',
  });

  res.render('pages/detail', {
    ...defaults,
    product,
  });
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

Upvotes: 0

Views: 1872

Answers (1)

crystal
crystal

Reputation: 241

Maybe you can check its data type before looping.

if (typeof collection !== "undefined" ) {
  collection.forEach((item) => {
   
   });
 }

I spot you using the same variable when loop the collection. You cannot use same name, it should be different name to represent the object/item in the collection

collection.forEach((collection) => {

Upvotes: 1

Related Questions