Next.js Application error: a client-side exception has occurred (see the browser console for more information)
Asked Answered
L

13

13

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;
Lombardi answered 13/6, 2022 at 19:14 Comment(1)
Sounds like 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 of products 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
F
22

I had this error, even though I got no errors at build time, it was extremely difficult to figure out took a couple days. It turned out some of my incoming data was rendering into some invalid html (something was wrong with a dynamically created script tag). I was able to solve this error by trial and error removing different pieces of incoming data and seeing if my pages would render. Would start there if I had to do it again.

Foreland answered 25/7, 2022 at 13:54 Comment(2)
Is there a way to change / customize that message ?Davilman
in my case there was a navigation component which navigate based on user.id when there is an authenticated user but when there is not authenticated it throw this error so what i did was use the question mark like this user?.id and my problem fixedSmarmy
W
1

I had the same error, but there could be any reason, I would recommend to check your html tags first. It is also was useful to run app in dev mode and carefully look at the errors in console. In my case the problem was in the incorrect transfer of props from the parent component to child and than to subchild, I was passing the function call in props. Solved the problem by creating a function in the final child component without passing. I hope this helps.

Womble answered 10/1, 2023 at 16:15 Comment(0)
S
1

The best way to debug these sorts of errors, and avoid your application from crashing is using React Error boundaries

https://nextjs.org/docs/advanced-features/error-handling#handling-client-errors

Snaggletooth answered 10/3, 2023 at 7:21 Comment(0)
A
1

During development, I had critical dependencie (i.e., lodash) defined in "devDependencies" instead of dependencies. This was causing the error in the deployment for me.

Alchemize answered 8/3 at 8:12 Comment(0)
G
0

I had this error, this what helped me in my project.

Screen from my Staging site (Heroku), (on Local there was no error)

enter image description here

on my local (dev mode) I have changed API to fetch from Staging site, rather Local (I am using Strapi CMS)

NEXT_PUBLIC_STRAPI_API='https://XXXXXXXXX.herokuapp.com/api'

My error on local, gave me more detailed error, Link in my case

enter image description here

To find where error was coming, in Layout.js file I uncommented one by one, 1) Header, 2) main, 3) Footer, it was Footer that generated error and fix Footer, no more error

enter image description here

Graben answered 27/10, 2022 at 18:12 Comment(0)
C
0

From my experience with this error message in production, it usually because of trying to access a null object, undefined or even props/functions that are doesn't exist in the object. One way to avoid these type of errors is to use typescript :)

Corbie answered 16/1, 2023 at 16:59 Comment(0)
F
0

For me, error was due to I missed environment variable on vercel dashboard. I only had .env file. After updating environment variable on dashboard, works fine.

Foreshadow answered 4/2, 2023 at 12:46 Comment(0)
J
0

Have you added your .local.env files to your vercel project in the settings? A client side error (from experience) on vercel usually occurs when you have not added your .local.env files in production. (Make sure you have copied all your environment variables to your clip board) To do this go to your Vercel project dashboard -> Settings -> Environment Variables -> Click on the 'Key' text field and paste the env's you copied -> Check production, preview and deployment -> Click save ->Go to your deployments and promote the latest (or a 'ready') to production. Hope this helps.

Jamima answered 16/3, 2023 at 20:23 Comment(0)
P
0

For me it was a cookie consent library i was using. Check that also if you are using one.

Prospero answered 27/4, 2023 at 9:9 Comment(0)
Y
0

For me, I was passing a null object to an Image component an asserting it as a string. On production it gave client side error. The source code was very obfuscated but if you dig around there should be a hint somewhere of what's going wrong.

Yurev answered 19/9, 2023 at 15:1 Comment(0)
E
0

In my own case, I installed a package that is likely incompatible with Next 12/React 18. Specifically, I found that Headless UI was the culprit; referenced in GitHub issue. One option was to downgrade to React 17, which I didn't really want.

What fixed it for me was disabling React Strict mode like this:

const nextConfig = {
  reactStrictMode: false,
  // other config here...
};

module.exports = nextConfig;

Hope this helps someone :)

Elissa answered 26/10, 2023 at 16:8 Comment(0)
M
0

In my case it was a devious bundling issue in my monorepo. I have a package where I use React and for god knows what reason, it bundles itself with react/jsx-runtime with dev and prod mode included. Now I did already exlude jsx-runtime as it's beautifully injected into the js bundle, bybassing my Rollup externalized ...Object.keys(pkg.dependencies || {}) completely.

However, it still includes some crap within the bundle which NextJS succeeds importing in local dev environment (macOS) but fails inside Docker container. It doesn't help that the error is as obtuse as 9816-21e2b556fd17598a.js:1 TypeError: X.jsxDEV is not a function

The solution in my case was to pass jsxRuntime: 'classic' to '@vitejs/plugin-react' in my vite.config.ts:

import react from '@vitejs/plugin-react'
export default defineConfig({
  ...
    rollupOptions: {
      external: [
        'react',
        'react/jsx-runtime',
        'react-dom',
        ...Object.keys(pkg.devDependencies || {}),
        ...Object.keys(pkg.dependencies || {})
      ],
      output: {
        globals: {
          react: 'react',
          'react-dom': 'ReactDOM',
          'react/jsx-runtime': 'react/jsx-runtime'
        }
      }
    },
  },
  plugins: [
    react({
      jsxRuntime: 'classic'
    }),
...
Malkin answered 27/6 at 8:19 Comment(0)
B
0

This for me was because I was missing some environment variables in wp engine atlas (im not using vercel).

Boorish answered 2/7 at 21:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.