API call using getStaticProps
Answered
Champagne D’Argent posted this in #help-forum
Champagne D’ArgentOP
I am fetching data from an express RESTful endpoint.
I face this error :
my application has the following folder structure:
I face this error :
./app\blog\page.tsx
ReactServerComponentsError:
"getStaticProps" is not supported in app/. Read more: https://nextjs.org/docs/app/building-your-application/data-fetching
File path:
./app\blog\page.tsxmy application has the following folder structure:
./app
./blog
page.tsx
./components
BlogPost.tsx
page.tsx
index.tsx
globals.css// this is my code for blog/page.tsx
import { GetStaticProps } from "next";
import BlogPost from "../components/BlogPost";
import axios from "axios";
export default function post1({posts}){
const posts_static = [
{id:"1",
title:"Task one",
date:"1st dec 2023",
author:"Author 1",
content:"Test description content"},
{id:"2",
title:"Task two",
date:"2nd dec 2023",
content:"Test description content"},
{id:"3",
title:"Task three",
author:"Author 2,
content:"Test description content"},
{id:"4",
title:"Task four",
content:"Test description content"},
]
return(
<main>
<h1>These are all the posts</h1>
<div>
{posts_static.map(
(post)=> <BlogPost key={post.id} id={post.id} title={post.title} date={post.date} author={post.author} content={post.content}/>)}
</div>
<img></img>
</main>
)
}
export async function getStaticProps(){
try{
const res = await axios.get('https://localhost:5000/api/post');
const posts = await res.data
console.log(posts)
return { props: {posts}}
}catch(error){
console.error("error fetching data:",error)
return {
props: {
posts: []
}
}
}
}Answered by Ray
export default async function post1(){
const {data} = await axios.get('https://localhost:5000/api/post');
return(
<main>
<h1>These are all the posts</h1>
<div>
{data.map(
(post)=> <BlogPost key={post.id} id={post.id} title={post.title} date={post.date} author={post.author} content={post.content}/>)}
</div>
<img></img>
</main>
)
}84 Replies
Champagne D’ArgentOP
what do you mean byt hat?
I can just call axios.get(path) for example?
Where can I use getStaticProps
getStaticProps can only be exported from a page. You cannot export it from non-page files, _app, _document, or _error.
One of the reasons for this restriction is that React needs to have all the required data before the page is rendered.
Also, you must use export getStaticProps as a standalone function — it will not work if you add getStaticProps as a property of the page component.
Good to know: if you have created a custom app, ensure you are passing the pageProps to the page component as shown in the linked document, otherwise the props will be empty.
getStaticProps can only be exported from a page. You cannot export it from non-page files, _app, _document, or _error.
One of the reasons for this restriction is that React needs to have all the required data before the page is rendered.
Also, you must use export getStaticProps as a standalone function — it will not work if you add getStaticProps as a property of the page component.
Good to know: if you have created a custom app, ensure you are passing the pageProps to the page component as shown in the linked document, otherwise the props will be empty.
this is what I pulled fromt he documentation
export default async function post1(){
const {data} = await axios.get('https://localhost:5000/api/post');
return(
<main>
<h1>These are all the posts</h1>
<div>
{data.map(
(post)=> <BlogPost key={post.id} id={post.id} title={post.title} date={post.date} author={post.author} content={post.content}/>)}
</div>
<img></img>
</main>
)
}Answer
Champagne D’ArgentOP
Thanks a lot ray! I am getting confused a little with app router and page router format. How could I learn more about this
@Ray Click to see attachment
Champagne D’ArgentOP
where did you get thsi from?
I just saw it on the top left! thank you
Champagne D’ArgentOP
@Ray I am getting an axios error. I don't think it is a CORS error as I have used express.use(cors());
what error?
Champagne D’ArgentOP
page.tsx:14 error:
AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
page.tsx:10
GET https://localhost:5000/api/post net::ERR_SSL_PROTOCOL_ERROR
getData @ page.tsx:10
eval @ page.tsx:19
Show 124 more frames
AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
page.tsx:10
GET https://localhost:5000/api/post net::ERR_SSL_PROTOCOL_ERROR
getData @ page.tsx:10
eval @ page.tsx:19
Show 124 more frames
The endpoint is running and I have tested it with postman
on https?
Champagne D’ArgentOP
what do you mean by on https?
is your backend running on https?
if so, try this maybe
const instance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
});
instance.get('https://something.com/foo');@Ray if so, try this maybe
ts
const instance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
});
instance.get('https://something.com/foo');
Champagne D’ArgentOP
I am just using localhost at the moment
It is http I believe
yea I changed it to http and it worked fine
Thanks for pointing me in the right direction
np
Champagne D’ArgentOP
@Ray could I consult you about something?
my current path is blog/{id}
/blog
pages.jsx
/[id]
page.jsximport {useRouter} from "next/router"
export default function postByID(){
const router = useRouter();
const id = router.query.id;
return(
<h1>Getting post by {id}</h1>
)
}This is the error that I receive : You have a Server Component that imports next/router. Use next/navigation instead.
Learn more: https://nextjs.org/docs/app/api-reference/functions/use-router
Learn more: https://nextjs.org/docs/app/api-reference/functions/use-router
how do I get the query parameter of id in this route?
found this
you should use
next/navigation for app routerChampagne D’ArgentOP
I figured it out
I think
but you get the params object in the props from page component
export default function postByID({ params }: { params: { id: string} }){
const id = params.id
return(
<h1>Getting post by {id}</h1>
)
}so you don't need to use
useRouter which require client componentChampagne D’ArgentOP
'use client'
import {useParams} from "next/navigation"
export default function postByID(){
const params = useParams();
const id = params.id
return(
<h1>Getting post by {id}</h1>
)
}THis works
I am using the router to now navigate to this page
well but marking the page component to be a client component will lose the ability to use server side api
Champagne D’ArgentOP
I get a not mounted error
@Ray well but marking the page component to be a client component will lose the ability to use server side api
Champagne D’ArgentOP
hmm I was thinking about that just now
Champagne D’ArgentOP
"use client";
import PropTypes from "prop-types";
import {useState} from "react";
import { useRouter } from "next/router";
function BlogPost({id, title ,date ,author ,content}){
const router = useRouter();
const [expanded, setExpanded] = useState(false);
const toggleContent= () =>{
console.log(`Click on post ${id}`)
router.push(`/${id}`)
setExpanded(!expanded);
}
return(
<div>
<div>
<h1>Title:{title}</h1>
<span>
<h3>Date:{date}</h3>
<h3>Author{author}</h3>
</span>
</div>
<div>
<p>content:{content}</p>
<button onClick={toggleContent}>read more</button>
</div>
</div>
)
}
BlogPost.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
date: PropTypes.string,
author: PropTypes.string,
content: PropTypes.string.isRequired
};
export default BlogPost;I thought I mounted it with useRouter();
-import { useRouter } from "next/router";
+import { useRouter } from 'next/navigation';always use
next/navigation instead of next/routerin app router
Champagne D’ArgentOP
do I really need to use a router?
can I use an a tag
for example :
<a href={`./${id}`}>read more</a>Champagne D’ArgentOP
when i use the a tag, the path is not maintained
you have to use Link for it
Champagne D’ArgentOP
instead of building off the current path it goes to localhost:3000/id
<Link href={`/blog/${id}`} />Champagne D’ArgentOP
<Link href={
./${id}} /> is this not valid?no you should provide the full path
@Ray ts
<Link href={`/blog/${id}`} />
like this
Champagne D’ArgentOP
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of
Check the render method of
BlogPost.why am I getting this error? I have my imports and exports properly defined
"use client";
import PropTypes from "prop-types";
import {useState} from "react";
import { Link } from "next/link";
function BlogPost({id, title ,date ,author ,content}){
// const router = useRouter();
const [expanded, setExpanded] = useState(false);
return(
<div>
<div>
<h1>Title:{title}</h1>
<span>
<h3>Date:{date}</h3>
<h3>Author{author}</h3>
</span>
</div>
<div>
<p>content:{content}</p>
<Link href={`/blog/${id}`}> Read more </Link>
</div>
</div>
)
}
BlogPost.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
date: PropTypes.string,
author: PropTypes.string,
content: PropTypes.string.isRequired
};
export default BlogPost;why are you using typescript with prop-types?
Champagne D’ArgentOP
I was originally using typescript and then I moved off it as it was something I am not too familiar with
ok where do you use BlogPost?
Champagne D’ArgentOP
I use it in blog
can you show the code
Champagne D’ArgentOP
"use client"
import BlogPost from "../components/BlogPost";
import axios from "axios"
import { useRouter } from "next/router.js";
import { useEffect, useState } from "react";
export default function post(){
const [postdata, setPostData ] = useState(null);
useEffect(() =>{
const getData = async () =>{
try{
console.log("connecting")
const res = await axios.get('http://localhost:5000/api/post/');
const data = await res.data
// console.log("data returned")
// console.log(data);
setPostData(data)
}catch(error){
console.error("error:", error)
}
}
getData();
},[])
return(
<main>
<h1>These are all the posts</h1>
<div>
{!postdata && <p>Loading the data</p>}
{postdata && postdata.map(
(post)=> <BlogPost key={post.id} id={post.id} title={post.title} date={post.date} author={post.author} content={post.content}/>)}
</div>
<img></img>
</main>
)
}remove this line
import { useRouter } from "next/router.js";Champagne D’ArgentOP
I removed it. However, the problem still persists
Champagne D’ArgentOP
that did not fix it
can you show BlogPost again
Champagne D’ArgentOP
"use client";
import {useState} from "react";
import Link from "next/link";
function BlogPost({id, title ,date ,author ,content}){
return(
<div>
<div>
<h1>Title:{title}</h1>
<span>
<h3>Date:{date}</h3>
<h3>Author{author}</h3>
</span>
</div>
<div>
<p>content:{content}</p>
<Link href={`/blog/${id}`}> Read more </Link>
</div>
</div>
)
}
// BlogPost.propTypes = {
// id: PropTypes.string.isRequired,
// title: PropTypes.string.isRequired,
// date: PropTypes.string,
// author: PropTypes.string,
// content: PropTypes.string.isRequired
// };
export default BlogPost;well it looks fine
restart the dev server maybe
Champagne D’ArgentOP
yea it works now
Thanks a lot