I am working on a personal project with Next.js and Typescript. I have an API call on the hello.ts that comes by default with the app. I added a JSON
file on there. Currently, I am having issues mapping that JSON
and rendering the content of it. At the moment, the JSON
is inside the useState, but when I try to do something with it the browser and the console give me errors.
This is the hello.ts
with a msaller JSON
located here /pages/api/hello
:
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
type Data = {
clientName: string
campaignName: string
userName: string
frames: {
id: string
asset: string
subheading: string
description: string
link: string
}[]
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
res.status(200).json({
userName: "username",
frames: [
{
id: "1",
asset: "",
subheading: "Instagram",
description: "",
link: "someurl.com"
},
{
id: "3",
asset: "",
subheading: "Facebook",
description: "username Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sollicitudin metus vitae",
link: "someurl.com"
}
] })
}
This is where I am calling the api located components/container
:
import { useEffect, useState } from "react";
import { FrameContainerProps } from "../../types";
const FrameContainer: React.FC<FrameContainerProps> = () => {
const [apiDetails, setapiDetails] = useState<any>();
useEffect(() => {
fetch('http://localhost:3000/api/hello')
.then((res) => {
return res.json();
})
.then(
(data) => {
setapiDetails(data);
},
(err) => {
return console.error(err);
}
);
}, []);
return (
<>
{Object.entries(apiDetails).map(detail => (
<h3>{detail.frames[i].description ? detail.frames[i].description : ''}</h3>
))}
</>
)
}
export default FrameContainer;
Also, how can I render the data only if it has values inside?
CodePudding user response:
Set the apiDetails
default value to null and add a check to see if the data has been loaded.
Also, you should map
on apiDetails.frames
:
import { useEffect, useState } from 'react';
import { FrameContainerProps } from '../../types';
const FrameContainer: React.FC<FrameContainerProps> = () => {
const [apiDetails, setapiDetails] = useState<any>(null);
useEffect(() => {
fetch('http://localhost:3000/api/hello')
.then((res) => {
return res.json();
})
.then((data) => {
setapiDetails(data);
})
.catch((err) => {
return console.error(err);
});
}, []);
if (!apiDetails) return <>Loading data...</>;
return (
<>
{apiDetails.frames && apiDetails.frames.map((frame) => (
<h3>
{frame.description || ''}
</h3>
))}
</>
);
};
export default FrameContainer;