Reputation: 712
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,
};
}
EDIT I recognized that the site works normally if I go straight to the link that I want... It stops working when I'm calling components with Link tags in nextJS then it throws an error that it's in title... So if I go straight to the link everything works as expected maybe that is also the reason that the page works if I click on my link and then refresh it... So what could be the problem with Link tag? This is my code for it:
<Link
href={{
pathname: "/restaurant/restaurantName/dashboard/",
query: {restaurantName: restaurantName},
}}
>
<div
className={
router.pathname == "/restaurant/[restaurantName]/dashboard"
? "text-blue-600 bg-gray-50"
: "text-gray-700 "
}
>
<div className="flex p-3 space-x-4 0 hover:bg-gray-50 hover:text-blue-600 cursor-pointer">
<DonutLargeIcon className=" text-gray-300" />
<p className="">Dashbord</p>
</div>
</div>
</Link>
Upvotes: 5
Views: 69073
Reputation: 21
Prevent accessing non existing element in your array
You try to access element of an empty array in your html code which causes this error since html is executed before you set data in useEffect
Which means you have no value in your array, ?
operator in value?.arr[0]
only works for the array but not for it's elements, just use value?.arr?.[0]
solution:
<div>info: {value?.arr?.[0].name}</div>
2nd solution that would fit in your restaurant code:
{value?.arr?.length > 0 && <>
<div>info: {value.arr[0].name}</div>
<div>disabled: {value.arr[0].disabled? "disabled" : "enabled"}</div>
</>
}'
PS: Guess most of ppl just care about the error not the specific code that this post has
Upvotes: 0
Reputation: 788
For someone who has tried get data from array inside an object and got this error - you can try to check with length
like this way:
object?.array.length ? object?.array?.someItem![0] : 'not exist'
Take attention that we check with chaining sign ([?]
) and logical NOT (!
) for more safe search.
Upvotes: 1
Reputation: 55
1-if data is undefined on the first component render I think this approach will work
const fetcher = async () => {
const response1 = await fetch("API");
const data1 = await response1.json();
const props = {
data: data1,
};
return props;
};
return props= {data: data1}
const {data} =useSWR("data",fetching)
it should be data.data.showItemOnOrderreturn (
<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>
);
Upvotes: 1
Reputation: 3230
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.
Upvotes: 0
Reputation: 381
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]);
Upvotes: 0