Home > Software engineering >  Cannot read properties of undefined (reading '0')
Cannot read properties of undefined (reading '0')

Time:11-08

I have a page coded in React with NextJS hooks, when I try to render a page the error says what's in the title, I presume because the object which I'm mapping is empty/undefined on first load. I added "?" to every map I have on the page and it's still giving me this error... I noticed that if I stay on that page after it gives me error and press "Ctrl shift r" the page loads normally. What could be causing this?

import {Fragment, useEffect} from "react";
import Head from "next/head";
import DashboardPage from "../../../../components/components/dashboard/DashboardPage";
import LayoutDashboard from "../../../../components/layout/LayoutDashboard";
import React from "react";
import Pusher from "pusher-js";
import useSWR, {mutate} from "swr";

const fetcher = async () => {
  const response1 = await fetch("API");
  const data1 = await response1.json();


  const props = {
    data: data1,
  };
  return props;
};

export default function Dashboard(props) {
  const {data, error} = useSWR("data", fetcher);

  useEffect(() => {
    //Pusher.logToConsole = true;
    var pusher = new Pusher("pshr", {
      cluster: "eu",
    });
    const channel = pusher.subscribe("chnl");
    channel.bind("chnl", function (data) {
      console.log(data);
      mutate("data");
    });
  }, []);

  if (error) return "Error";
  if (!data) return "Loading";

  console.log(data);
  return (
    <Fragment>
      <Head>
        <title>Dashboard</title>
        <link rel="icon" href="/favicon.ico" />
       
      </Head>

      <LayoutDashboard restaurantData={props?.restaurantData[0]}>
        <DashboardPage
          orders={data?.showItemsOnOrder}
          dashboardCards={data?.dashboardCardInfo}
          ordersGraph={data?.dashboardGraph}
        />
      </LayoutDashboard>
    </Fragment>
  );
}

export async function getStaticPaths() {
  const response = await fetch(`API`);
  const data = await response.json();

  const tables = [];
  for (var i = 1; i <= data[0].restaurantTables; i  ) {
    tables.push({
      restaurant: data[0].queryName,
      tableNr: i.toString(),
    });
  }

  return {
    paths: tables.map((table) => {
      return {
        params: {
          restaurantName: table.restaurant,
          tableNr: table.tableNr,
        },
      };
    }),
    fallback: false,
  };
}

export async function getStaticProps() {
  const response = await fetch(`API`);
  const data = await response.json();

  return {
    props: {
      restaurantData: data,
    },
    revalidate: 1,
  };
}

CodePudding user response:

Your useEffect needs data in it's dependency array for it to trigger a rerender based on data. Also, you'll need if (!data) return at the top of this useEffect to prevent the error.

So:

useEffect(() => {
    //Pusher.logToConsole = true;
    if (!data) return

    var pusher = new Pusher("pshr", {
      cluster: "eu",
    });

    const channel = pusher.subscribe("chnl");

    channel.bind("chnl", function (data) {
      console.log(data);
      mutate("data");
    });
  }, [data]);

CodePudding user response:

What could be causing this?

The data is undefined in your function getStaticPaths.

  export async function getStaticPaths() {
    const response = await fetch(`API`);
    const data = await response.json(); // <-- here, your data is undefined

Now I don't use fetch, but I think it doesn't throw in case of 4xx or 4xx errors. Checking MDN yes, you need to check if the response is actually OK. Something like this:

  export async function getStaticPaths() {
    const response = await fetch(`API`);
    if (!response.ok) {
      throw new Error('Network response was not OK');
    }

    const data = await response.json(); // <-- now this won't be undefined

You can read more about this behavior here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#checking_that_the_fetch_was_successful

EDIT Sorry, I have just noticed that you also reference props?.restaurantData[0].

So instead of <LayoutDashboard restaurantData={props?.restaurantData[0]}> use <LayoutDashboard restaurantData={props?.restaurantData ? props?.restaurantData[0] : undefined}> like here:

<LayoutDashboard restaurantData={props?.restaurantData ? props.restaurantData[0] : undefined}>
  <DashboardPage
    orders={data?.showItemsOnOrder}
    dashboardCards={data?.dashboardCardInfo}
    ordersGraph={data?.dashboardGraph}
  />
</LayoutDashboard>

That's because, by putting an optional chaining operator (?) after props, you only try to read restaurantData if props is not undefined. But since it's not, then you try to access the first element in restaurantData by using restaurantData[0] without checking if restaurantData is actually defined.

Check that the restaurantData is defined and access restaurantData[0] only if it's defined.

CodePudding user response:

1-if data is undefined on the first component render I think this approach will work

  • first-time data is undefined
  • sec time data is fetched then u can use as below
const fetcher = async () => {
  const response1 = await fetch("API");
  const data1 = await response1.json();


  const props = {
    data: data1,
  };
  return props;
};
  • if look at ur fetching function u return props= {data: data1}
  • const {data} =useSWR("data",fetching) it should be data.data.showItemOnOrder
return (
    <Fragment>
      <Head>
        <title>Dashboard</title>
        <link rel="icon" href="/favicon.ico" />
       
      </Head>

      <LayoutDashboard restaurantData={props?.restaurantData[0]}>
       {data&& <DashboardPage
          orders={data.data.showItemsOnOrder}
          dashboardCards={data.data.dashboardCardInfo}
          ordersGraph={data.data.dashboardGraph}
        />}
      </LayoutDashboard>
    </Fragment>
  );
  • Related