Seeing the above error when trying to load a page that renders product information that has been pulled from an external API. Error only occurs in production environment and everything runs fine locally. When checking the console I get this error:
TypeError: undefined is not a function (near '...n.map...')
"Next Build" works fine and builds a production build. "Next Start" works fine as well and there are no errors thrown in the console or anywhere else. Error only occurs once I have pushed to the production environment. Confused as to whats going on. I have my code below:
Component thats rendering the list of products:
import type { NextPage } from 'next'
import React, { useState, useEffect, useContext} from 'react';
import styles from '../styles/Home.module.css'
import DepopIcon from './icons/depop.svg'
import { Image, Main, Heading, Paragraph, Nav, Icons, Header, Grommet, Box, Button, Grid, Text, Footer, Anchor } from 'grommet';
import {
Instagram,
Shop,
Cart
} from 'grommet-icons';
import { useRouter } from 'next/router';
export default function ProductsList() {
const router = useRouter();
// load our products state variable
const [products, setProducts] = useState([]);
const [prodImg, setProdImg] = useState([]);
function handleProdClick(id){
router.push({ pathname: "/product", query: { id: id } })
}
const getProducts = async () => {
const response = await fetch("/api/getproducts");
var data = await response.json();
data = JSON.parse(data);
await setProducts(data);
}
useEffect(() => {
getProducts();
}, [])
//
// build areas list for our grid
const areaVar = "area";
const cols = 3;
var r = 0;
var c = 0;
var areas = []
for (let x = 1; x < products.length+1; x++){
const name = areaVar+x.toString()
areas.push({ name: name, start: [r,c], end: [r,c] })
r += 1
if (x % 3 == 0){
r = 0
c += 1
}
}
//
console.log(products);
// create our product objects for our grid
var productObjs = [];
if (typeof products != "undefined" && products != null){
productObjs = products.map((product, index) => {
return(
<Box
key={product._id}
gridArea= {areas[index].name}
background="#003311"
direction="column"
pad="none"
align="center"
onClick={() => {handleProdClick(product._id)}}
>
<Image
src={product.frontImage} fill={true} fit="cover"
onMouseOver={e => (e.currentTarget.src = product.backImage)}
onMouseOut={e => (e.currentTarget.src = product.frontImage)}
/>
<Box
direction="row"
pad="xsmall"
align="center"
gap="large"
justify="between"
animation="fadeIn"
>
<Text color="#fff" size="medium">{product.name}</Text>
<Text color="#fff" size="medium">{product.color}</Text>
<Text color="#fff" size="medium">{product.price} USD</Text>
<Text color="#fff" size="medium">{product.size}</Text>
</Box>
</Box>
);
});
}
//
const rows = []
for (let i = 0; i < r; i++){
rows.push('large')
}
return (
<Grid
rows={rows}
columns={['flex', 'flex', 'flex']}
gap="none"
areas={areas}
>
{productObjs}
</Grid>
);
}
Page that is using the above component:
import type { NextPage } from 'next'
import React, { useState, useContext, useEffect} from 'react';
import { Paragraph, Main, Nav, Icons, Header, Grommet, Box, Button, Grid, Text, Footer, Anchor } from 'grommet';
import ContactHeaderUnit from '../components/ContactHeaderUnit.tsx'
import FooterUnit from '../components/FooterUnit.tsx'
import ProductsList from '../components/ProductsList.tsx'
const Shop: NextPage = () => {
return (
<Grommet
full={true}
background="#fffced"
theme={{
global: { font: {
family: "Alice"
}},
paragraph: {
font: {
family: 'Arial',
},
},
label: {
font: {
family: 'Arial',
},
},
}}
>
<ContactHeaderUnit/>
<ProductsList/>
<FooterUnit/>
</Grommet>
)
}
export default Shop;
products
doesn't have a.map
function, which would imply that whatever you set there is not an array in production. Perhaps in production, your request is being blocked by the remote server, or altered in a way that differs from local. Check the data type ofproducts
when you set it so you can observe. You can put a breakpoint in that code, log it, etc. You really shouldn't be setting that state if it's not an array, and checks like (typeof products != "undefined" && products != null) seem redundant if you were type checking before setting invalid state. – Denominative