I have a folder structure like this in my next app
├───blogs
│ ├───[slug].js
│ └───index.js
...
I published 2 blogs in Strapi. Lets say firstBlog and secondBlog.
In local everything works fine. But in a deployed app from vercel when I go to details of firstBlog everything works fine. But for the secondBlog it says 404 not found. I looked for answers but couldn’t find the problem. My slug.js:
import Layout from '../../components/Layout/layout'
import BlogPost from '../../components/Blog/blog'
import api from '../../api'
const Blog = ({ blog }) => {
return (
<Layout>
<BlogPost blog={blog} />
</Layout>
)
}
export const getStaticPaths = async () => {
const response = await api.getAllBlogs()
const paths = response.map(path => {
return {
params: {slug: path.attributes.slug.toString()}
}
})
return {
paths,
fallback: false
}
}
export const getStaticProps = async (context) => {
const slug = context.params.slug
const response = await api.getSingleBlog(slug)
return {
props: { blog: response }
}
}
export default Blog
and my api call is such as:
getSingleBlog(slug) {
return this.execute("get", `blogs?filters[slug]=${slug}&populate=categories`);
},
I think this is about my deployment in vercel. But couldn’t find the solution. Any ideas ?
Related
When I test getServerSideProps() in development mode, prop data in my landing page is updated constantly, because the app is under fast build mode.
But when the app is deployed in vercel, the data in landing page is not updated even though my database (mongoDB) has been updated.
If I check Heroku logs (where backend is deployed), there is no POST request by client when I (user) visit landing page second time. Therefore, I am assuming that my browser uses the cached html page and not sending request to server.
Could anyone help me to explain what is the issue?
import { ApolloClient, InMemoryCache } from "#apollo/client";
import { GetServerSideProps } from "next";
import { GetAllPosts as query } from "#network/queries";
const client = new ApolloClient({
uri: //my backend uri,
cache: new InMemoryCache(),
});
//pages/_app.ts
import type { AppProps } from "next/app";
function MyApp({ Component, pageProps }: AppProps) {
return (
<ApolloProvider client={client}>
<AuthContext.Provider value={authService}>
<Component {...pageProps} />
</AuthContext.Provider>
</ApolloProvider>
);
}
//pages/index.tsx
export const getServerSideProps: GetServerSideProps = async () => {
let posts = [];
try {
const {
data: { getAllPosts },
} = await client.query({ query });
posts = !!getAllPosts.length && getAllPosts;
} catch (err) {
console.error(`----------error --------- ${err}`);
} finally {
return {
props: {
posts,
},
};
}
};
export default function Landing({ posts }: Props) {
////// react code
}
I am fetching all posts from the backend from the API call http://localhost:3000/api/jobs and it is working perfectly by using getstaticProps(). Now I want to get a particular post based on slug and my API call is http://localhost:3000/api/jobs/:slug and it perfectly working API call But whenever I used the code shown below for dynamic routes it shows me a server error on the frontend and unable to fetch particular post data.
[slug].js
export const getStaticPaths = async () => {
const res = await fetch(`${API}/jobs`);
const post = await res.json();
const paths = post.map(job => {
return {
params: { slug: job.slug }
}
})
return {
paths,
fallback:true
}
}
export const getStaticProps = async (ctx) => {
const slug = ctx.params.slug;
const [job, photo] = await Promise.all([
fetch(`${API}/jobs/${slug}`).then(r => r.json()),
`${API}/jobs/photo/${slug}`
]);
if (!job) {
return {
notFound:true
}
}
return {
props: {
job,
photo
},
revalidate:60
}
}
Also whenever I used another API call like http://localhost:3000/api/jobs-edit which has the same function as that of http://localhost:3000/api/jobs inside getStaticPaths() then it performs well and gives us single post data.
What can be the problem?
i have created a nextjs app, i'm getting data from an express server deployed on netlify. i have created two pages, the first to display a list of users (i've got the users with getServerSideProps() function) and the second page is when you click on a user, you'll be redirected to the user profile (i've got the user's data with getStaticProps() and getStaticPaths() functions).
On localhost everything works fine.
But when i've tried to deploy the app on Netlify, i got this error while building it:
> Build error occurred 11:24:20 PM: Error: Export encountered errors on following paths /users/[userid]
The users list file:
import styles from "../../styles/Home.module.css";
import Link from "next/link";
export default function Users({ users }) {
return (
<div className={styles.container}>
{users.map((user) => (
<Link href={`/users/${user._id}`} key={user._id}>
{user.firstname}
</Link>
))}
</div>
);
}
export async function getServerSideProps() {
const res = await fetch("https://***************/api/users");
const users = await res.json();
return { props: { users} };
}
The profile file:
import React from "react";
export default function singleUser({ user }) {
return (
<div>
<h1>Hello {user.firstname}!</h1>
</div>
);
}
export async function getStaticPaths() {
const res = await fetch("https://***************************/api/users");
const users = await res.json();
const paths = users.map((user) => ({
params: { userid: user._id },
}));
return { paths, fallback: true };
}
// This also gets called at build time
export async function getStaticProps({ params }) {
const res = await fetch(`https://**********************/api/users/${params.userid}`);
const user = await res.json();
return { props: { user: user || {} }, revalidate: 3600 };
}
Hi I'm using NextJs and I am having an issue that when my app is hosted on my local server the pages that are pre loaded with getStaticProps are loading in a few ms but when hosted on Vercel it is taking 300ms to load.
Does anyone have any suggestions on how I can get my pages to load quicker on Vercel?
My app is currently hosted at https://next-movie-delta.vercel.app/
and my github repo is https://github.com/lewisRotchell/next-movie
My getStaticPaths code looks like:
export async function getStaticPaths() {
const movies = await getMovies();
const bigMovieArray = [
...movies[0].results,
...movies[1].results,
...movies[2].results,
];
const paths = bigMovieArray.map((movie) => ({
params: { movieId: movie.id.toString() },
}));
return {
paths,
fallback: "blocking",
};
}
and the getMovies code looks like :
export async function getMovies() {
const urls = [newReleasesUrl, popularMoviesUrl, topRatedMoviesUrl];
try {
let data = await Promise.all(
urls.map((url) => fetch(url).then((response) => response.json()))
).catch((error) => console.log(error));
return data;
} catch (error) {
console.log(error);
}
}
Thanks :)
I've managed to fix the problem! I changed the linking from withRouter to a tag from next/link and it has fixed my issue!
For example, I have a dynamic route /blog/[article-id].
When visiting an existing blog post /blog/id-that-exist, it works as expected, and now I want to handle the case /blog/id-that-does-not-exist properly.
The code in /blog/[id].jsx looks something like:
export const getStaticPaths async () => {
return {
fallback: true,
paths: (await sequelize.models.Article.findAll()).map(
article => {
return {
params: {
pid: article.slug,
}
}
}
),
}
}
export const getStaticProps async () => {
// Try to get it from the database. Returns none if does not exist.
const article = await sequelize.models.Article.findOne({
where: { slug: pid },
});
return { props: { article: article } };
}
const ArticlePage = (props) => {
// This can happen due to fallback: true while waiting for
// a page that was not rendered at build time to build.
const router = useRouter()
if (router.isFallback) {
return <div>loading</div>;
}
return (
<div>{props.article.body}</div>
);
};
export const getStaticPaths = getStaticPathsArticle;
export const getStaticProps = getStaticPropsArticle;
export default ArticlePage;
I saw this related question: How to handle not found 404 for dynamic routes in Next.js which is calling API? but I'm not sure if it's the same as I'm asking here, as this does not depend on any external API being used.
notFound: true from Next.js 10
Starting in Next.js 10, we can do:
export const getStaticProps async () => {
// Try to get it from the database. Returns none if does not exist.
const article = await sequelize.models.Article.findOne({
where: { slug: pid },
});
if (!article) {
return {
notFound: true
}
}
return { props: { article: article } };
}
as documented at: https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation
When notFound is returned, the rendering function ArticlePage just never gets called, and the default 404 page is returned instead.
Note however that ArticlePage did get
For some reason in development mode:
I don't get the expected 404 HTTP status code
ArticlePage, so if you forgot to handle the fallback case, the it might crash due to missing properties
which was confusing me a bit. But in production mode, everything works as expected.
Workaround before Next.js 10
As shown https://github.com/vercel/next.js/discussions/10960#discussioncomment-1201 you could previously do something like:
const ArticlePage = (props) => {
if (!props.article) {
return <>
<Head>
<meta name="robots" content="noindex">
</Head>
<DefaultErrorPage statusCode={404} />
</>
}
return (
<div>{props.article.body}</div>
);
};
but this is not ideal because it does not set the HTTP return code correctly I believe, and I don't know how to do it.
Tested on Next.js 10.2.2.
I've read your answer regarding the solution after Next.js v.10, but I didn't get what was the problem in showing the expected http 404 code during development.
I use Next.JS v.12 and I get the expected 404 normally in development
import { GetStaticPaths, GetStaticProps } from 'next'
import { useRouter } from 'next/router'
import { ParsedUrlQuery } from 'querystring'
import Loading from '../../components/loading'
export const getStaticPaths: GetStaticPaths = async () => {
//your paths
return { paths, fallback: true }
}
export const getStaticProps: GetStaticProps = async ({ params }: { params?: ParsedUrlQuery }) => {
//get your props
if (!target){
return {notFound: true}
}
return { props: { ... }, revalidate: 86400}
}
function Index({ ... }) {
const router = useRouter()
if (router.isFallback) {
return <Loading />
}
return (
<div>
//my content
</div>
)
}
export default Index
When the target isn't found, it renders my custom 404 component in pages/404.tsx if I created one or just the default 404 page.
This should work normally during development and production.