I am getting Cannot read property 'map' of undefined when using getStaticProps in next.js inside components/featured-posts.js but if i use it directly on pages/index.js page it shows the results, anybody know why its doing this?
export async function getStaticProps(){
const data = await fetch('http://localhost/newblog/newblogapi/posts')
const posts=await data.json();
return {
props: { posts }, // will be passed to the page component as props
}
}
const FeaturedPosts = ({posts}) => {
console.log(posts)
return (
<div className="album py-5 bg-light">
<div className="container mt-5">
{ posts.map(post=>(
<div key={post.id}>
<h3>{post.title}</h3>
</div>
))}
</div>
</div>
);
}
export default FeaturedPosts;
You can only use getStaticProps on pages (files in the /pages directory), not in regular React components. I suggest you get the posts in your pages/index.js file and pass them as props to the FeaturedPosts component.
Related
This error makes no sense at all. This is the error I get when trying to get data from my firestore database.
TypeError: Cannot read property 'map' of undefined
I think it is a firebase firestore related error but it is giving me that error which makes it hard for me to know what exactly is wrong because I know that is not the problem. This is where page where I have the code where I am extracting the data using getStaticProps
import img from "./img.png";
import Image from 'next/image';
import styles from "../styles/Card.module.css";
import { db } from "../firebase";
import { collection, getDocs } from 'firebase/firestore';
export const getStaticProps = async () => {
const reference = collection(db, "students");
const data = await getDocs(reference);
const theData = data.docs.map(doc => ({...doc.data(), id: doc.id}));
console.log(data.name);
return {
props: {students: data}
}
}
function Card({students}) {
return (
<div className={styles.cardContainer}>
{students.map(student => (
<div className={styles.card}>
<div className={styles.first}>
<Image src={student.img} className={styles.imgr} width={200} height={150} alt="ima" placeholder='yeah bitch' />
</div>
<div className="second">
<h3>{student.name}</h3>
<p>{student.surname}</p>
</div>
</div>
))}
</div>
)
}
export default Card
This seems to me more like a firestore related problem not a looping problem. Where could I be going wrong?.
Based on your comment it runs just fine in useEffect but now it is failing. My guess is that it is failing on the server, and not on the client. useEffect does not ever run on the SSR. This is purely a hunch based on the data I have.
You could research how to check if you are on the server, and if so pass an empty array so students is not undefined. Or you could just always check for undefined and replace it with an empty array.
function Card({students}) {
const definedStudents = students ?? []
return (
<div className={styles.cardContainer}>
{definedStudents.map(student => (
<div className={styles.card}>
<div className={styles.first}>
<Image src={student.img} className={styles.imgr} width={200} height={150} alt="ima" placeholder='yeah bitch' />
</div>
<div className="second">
<h3>{student.name}</h3>
<p>{student.surname}</p>
</div>
</div>
))}
</div>
)
}
Though the data is showing in the console but I am missing something. I am new to NextJS and Sanity.io. So Kindly help. Nextjs code is not showing data in the frontend.
This is the NextJs code:
import React from "react";
// import Layout from '../components/Layout';
import client from '../utils/client';
export const TermsAndPolicy = (props) => {
return (
<>
<div className="ease-in">
<div>
<h1 className="text-3xl font-medium text-center my-4">Terms and Conditions</h1>
<h4 className="text-xl mx-8 py-8 ">
<span>Last Updated:{props.terms.dateUpdated}</span>
</h4>
</div>
<div>
<div>
<h2>{props.title}</h2>
</div>
<p className="md:text-justify text-center mx-8 py-8">
{props.body}
</p>
</div>
</div>
</>
);
};
export default TermsAndPolicy;
export const getServerSideProps = async () => {
const query = `*[_type == "terms"]{
title,
subHeading,
dateUpdated,
url,
body
}`;
const terms = await client.fetch(query)
console.log(terms);
return {
props: {
terms
}
};
}
I have added the NextJs code above which shows that I have called the client and connected the app. But somehow I am unable to show the data from the backend into the frontend. Data in the console is showing as you can see below! So therefore it is connected properly. The data below is the data showing in console:
But data is not showing in the website. It is showing blank instead.
I added a weather component in my app that fetches weather from open weather map. It works fine until I refresh the page, then it breaks.
If I comment the weather component out when refreshing and then add it back in when loaded it renders and works.
I'm not sure what's causing this error.
Here's some images of the console after refreshing for reference.
It seems to be undefined when refreshed. What's causing this issue?
// Weather component is called as normal in Home page
<div className="main-section-one">
<Weather />
<ToDoWidget />
</div>
import React, { useEffect, useState } from 'react'
//CSS
import '../css/Weather.css'
function Weather() {
// API
const URL = 'https://api.openweathermap.org/data/2.5/weather?q=barcelona&appid=APIKEY';
// State
const [weatherDetails, setWeatherDetails] = useState({});
async function getWeather() {
let fetchUrl = await fetch('https://api.openweathermap.org/data/2.5/weather?q=barcelona&appid=APIKEY&units=metric');
let data = await fetchUrl.json()
setWeatherDetails(data)
}
//Use Effect
useEffect(() => {
getWeather();
}, [])
return (
<div className="weather-container">
<div className="weather-one">
<div className="city">
<h3>Barcelona</h3>
<h1 className='temp'>{weatherDetails.main.temp}°C</h1>
</div>
<div className="current-weather">
<h3 className='current'>Sunny</h3>
</div>
</div>
<div className="weather-two">
<div className="">
<p>{weatherDetails.main.feels_like}°C</p>
<p className='weather-details'>Feels Like</p>
</div>
<div className="">
<p>{weatherDetails.main.humidity}%</p>
<p className='weather-details'>Humidity</p>
</div>
<div className="">
<p>{weatherDetails.wind.speed} MPH</p>
<p className='weather-details'>Wind Speed</p>
</div>
</div>
</div>
)
}
export default Weather
The main and wind properties may be undefined. Secure it.
<h1 className='temp'>{weatherDetails.main?.temp}°C</h1>
^^^ optional chaining
<p>{weatherDetails.wind?.speed} MPH</p>
Reference: Optional chaining
I am making a simple website and I would like to fetch data from an API and display it on my component.
The problem is that the getStaticProps() method is never called.
Here is the code of the component :
import React from "react";
import {GetStaticProps, InferGetStaticPropsType} from "next";
type RawProject = {
owner: string;
repo: string;
link: string;
description: string;
language: string;
stars: number;
forks: number;
}
function Projects({projects}: InferGetStaticPropsType<typeof getStaticProps>) {
console.log(projects);
return (
<section id="projects" className="bg-white p-6 lg:p-20">
<h1 className="sm:text-4xl text-2xl font-medium title-font mb-4 text-gray-900 pb-6 text-center">
Quelques de mes projets
</h1>
{/*
<div className="container px-5 mx-auto">
<div className="flex flex-wrap">
{rawProjects.map((project: RawProject) => (
<ProjectCard
title={project.repo}
language={project.language}
description={project.description}
imageUrl="https://dummyimage.com/720x400"
repoUrl={project.link}
/>
))}
</div>
</div>
*/}
</section>
);
}
export const getStaticProps: GetStaticProps = async () => {
console.log("getStaticProps()");
const res = await fetch("https://gh-pinned-repos-5l2i19um3.vercel.app/?username=ythepaut");
const projects: RawProject[] = await res.json();
return !projects ? {notFound: true} : {
props: {projects: projects},
revalidate: 3600
};
}
export default Projects;
The full code can be found here : https://github.com/ythepaut/webpage/tree/project-section
I am not sure if the problem is caused by the fact that I use typescript, or that I use a custom _app.tsx
I tried the solutions from :
https://github.com/vercel/next.js/issues/11328
How to make Next.js getStaticProps work with typescript
but I couldn't make it work.
Could someone help me please ?
Thanks in advance.
getStaticProps() is only allowed in pages.
Your code at the moment is :
import Hero from "../sections/Hero";
import Contact from "../sections/Contact";
import Projects from "../sections/Projects"; // you cannot call getStaticProps() in this componenet
function HomePage(): JSX.Element {
return (
<div className="bg-gray-50">
<Hero />
<Projects />
<Contact />
</div>
);
}
export default HomePage;
Instead call getStaticProps() inside index.tsx and pass the props to the component something like this ::
import Hero from "../sections/Hero";
import Contact from "../sections/Contact";
import Projects from "../sections/Projects";
function HomePage({data}): JSX.Element {
return (
<div className="bg-gray-50">
<Hero />
<Projects data={data} />
<Contact />
</div>
);
}
export const getStaticProps: GetStaticProps = async () => {
console.log("getStaticProps()");
const res = await fetch("https://gh-pinned-repos-5l2i19um3.vercel.app/?username=ythepaut");
const projects: RawProject[] = await res.json();
return !projects ? {notFound: true} : {
props: {projects: projects},
revalidate: 3600
};
}
export default HomePage;
Data fetching methods in NextJs like getStaticProps runs only on the server. Hence it works only in pages, not in a regular react component
Please Check their docs
For data fetching in Normal Components, You can only do client-side Rendering. NextJS recommends using this library SWR
According to their docs
SWR is a strategy to first return the data from cache (stale), then send the fetch request (revalidate), and finally, come with the up-to-date data.
You can only use getInitialProps, getServerSideProps, getStaticProps in Next.js pages
I checked your project and saw that your Project.tsx was in a component folder, but it needs to be in pages folder for those functions to work.
I got a similar bad experience because of bad service worker implementation, if you found it works with "Empty Cache and Hard Reload", you should check your service-worker code, you may don't want to cache any pages.
In pages folder you must export getStaticProps too
Example
export { default } from '../../games/tebak-kata/game';
export { getStaticPaths } from '../../games/tebak-kata/game';
export { getStaticProps } from '../../games/tebak-kata/game';
Recently I made a question about this problem: typeError: Cannot read property 'map' of undefined.
I want to use a component with getStaticProps and put it in my pages/index.js, but I can't with my current code. BUT, if I put this component as a page (pages/component.js) and open like a different page it just work as it should do.
The component Galery.js code:
import styles from '../styles/galery.module.css'
import Image from 'next/image'
import Link from 'next/link'
import photo from '../public/01.png'
export const getStaticProps = async () => {
const res = await fetch('https://my-json-server.typicode.com/Leterinho/PortfolioInteriorDesign/card');
const datas = await res.json();
return {
props: { datas }
}
}
const Galery = ({ datas }) => {
return (
<div className={styles.galeryPage}>
<h1 className={styles.title}>Projetos</h1>
<div className={styles.galery}>
<div className={styles.categoryWrapper}>
<h4 className={styles.subTitle}>Escritório</h4>
<div className={styles.lineWrapper}>
<a className={styles.leftArrow}>❮</a>
<div className={styles.line}>
{datas.map((data) => (
<div className={styles.imageBox}>
<Image src={photo} width={400} height={200} layout="responsive" lazy="true" placeholder="blur" />
<div className={styles.linkContent}>
<span className={styles.name} key={data.id}>{data.name}</span>
<Link href=""><a className={styles.link}>Veja Mais!</a></Link>
</div>
</div>
))}
</div>
<a className={styles.rightArrow}>❯</a>
</div>
</div>
</div>
</div>
);
}
export default Galery;
API link: https://my-json-server.typicode.com/Leterinho/PortfolioInteriorDesign/card
And this is the structure that I would like to have:
Desirable Structure
And this is the structure that works as a page:
Structure that works
What I should do to work as I planned?
Data fetching methods like getStaticProps can only be used from page components (components inside pages folder). I'd suggest you fetch the data at the page level in index.js, and pass it down to your Galery component.
juliomalves is correct! Thanks.