Dynamic Content not loading in NextJs Dynamic Pages - next.js

Currently I have a Blogs collection type in my Strapi CMS with an Id and title data fields. I'm using NextJs for my frontend to dynamically load blog content for each blog page. But my content doesn't load when my dynamic page is loaded.
Page where individual blogs are stored:
{posts &&
posts.map((item, idx) => (
<Link href={`/BlogPage/${item.id}`}>
<div>
<img src={`http://localhost:1337${item.Thumbnail.url}`}/>
</div>
</Link>
Then inside my BlogPage directory i have a file [id].js:
export default function name({blog}) {
return (
<>
<div>
{blog.Title}
</div>
</>
)}
// Tell nextjs how many pages are there
export async function getStaticPaths() {
const res = await fetch("http://localhost:1337/blogs");
const posts = await res.json();
const paths = posts.map((blog) => ({
params: { id: blog.id.toString() },
}));
return {
paths,
fallback: false,
};
}
// Get data for each individual page
export async function getStaticProps({ params }) {
const { id } = params;
const res = await fetch(`http://localhost:1337/blogs?id=${id}`);
const data = await res.json();
const posts = data[0];
return {
props: { posts },
};
}
This takes me to this URL http://localhost:3000/BlogPage/1 and gives me an error
TypeError: Cannot read property 'Title' of undefined

Try to out the getStaticProps and getStaticPaths of name function
export async function getStaticPaths() {
const res = await fetch("http://localhost:1337/blogs");
const posts = await res.json();
const paths = posts.map((blog) => ({
params: { id: blog.id.toString() },
}));
return {
paths,
fallback: false,
};
}
export async function getStaticProps({ params }) {
const { id } = params;
const res = await fetch(`http://localhost:1337/blogs?id=${id}`);
const data = await res.json();
const posts = data[0];
return {
props: { posts },
};
}
export default function name({posts }) { // change this line
return (
<>
<div>
{posts.Title} // change this line // Are you sure is it Title? not title? if it is with lowercase, it will return null
</div>
</>
)
}

Related

Displaying data from SWAPI

I am trying to display film details from this API https://swapi.dev/api/films in NextJS but I keep getting an error. It has something to do with the getStaticPath function. I am using this code: any help welcome.
import fetch from 'isomorphic-unfetch';
export const getStaticPaths = async () => {
const res = await fetch('https://swapi.dev/api/films');
const data = await res.json();
console.log("This is " + JSON.stringify(data));
const paths = data.results.map(film => {
return {
params: { id: film.episode_id.toString() },
};
});
return {
paths,
fallback: false,
};
};
export const getStaticProps = async (context) => {
const id = context.params.id;
const res = await fetch(`https://swapi.dev/api/films` + id);
const data = await res.json();
return {
props: { film: data },
};
};
const Details = ({ film }) => {
return (
<div>
<h1>Episode {film.episode_id}</h1>
<h1>{film.title}</h1>
</div>
);
};
export default Details;
I am expecting the episode ID and title to display
enter image description here
I have tried taking 'results' out of 'data.results.map', so 'data.map' but just results in a error says data.map is not a function...I guess because data is an object not an array. But results is an array so I am still lost. I do think the issue lies here somewhere though...

Next.js reference error "client" is not defined

I am having an error when trying to fetch product data from sanity with getStaticPaths
here is my code:
import React, { useState } from "react";
function ProductPage({ product, products }) {
const { image, name, details, price } = product;
return (
<div className="pdPage">
<div className="container">{name}</div>
</div>
);
}
export default ProductPage;
export const getStaticPaths = async () => {
const query = `*[_type == "product"] {
slug {
current
}
}
`;
const products = await client.fetch(query);
const paths = products.map((product) => ({
params: {
slug: product.slug.current,
},
}));
return {
paths,
fallback: "blocking",
};
};
export const getStaticProps = async ({ params: { slug } }) => {
const query = `*[_type == "product" && slug.current == '${slug}'][0]`;
const productsQuery = '*[_type == "product"]';
const product = await client.fetch(query);
const products = await client.fetch(productsQuery);
console.log(product);
return {
props: { products, product },
};
};
And then I get reference error client is not defined from getstatic client.fetch
I even delete my code and replace from tutor github repository, but get the same error
After figure it out sometimes I found that I forgot to import client from

How to update page when data is changed in nextjs?

When I delete one of the notes, it deletes from the DB. And to see the effect, I need to reload the page every time I delete a note.
How do I see the not deleted notes without reloading the page?
Here's the code for my page:
export default function Home(notes) {
const [notesData, setNotesData] = useState(notes);
const deleteNote = async (note) => {
const res = await fetch(`http://localhost:3000/api/${note}`, {
method: "DELETE",
});
};
return (
<div>
<h1>Notes:</h1>
{notesData.notes.map((note) => {
return (
<div className="flex">
<p>{note.title}</p>
<p onClick={() => deleteNote(note.title)}>Delete</p>
</div>
);
})}
</div>
);
}
export async function getServerSideProps() {
const res = await fetch(`http://localhost:3000/api`);
const { data } = await res.json();
return { props: { notes: data } };
}
If you're fetching the data with getServerSideProps you need to recall that in order to get the updated data like this :
import { useRouter } from 'next/router';
const router = useRouter()
const refreshData = () => router.replace(router.asPath);
But also you can store the data from getServerSideProps in a state and render that state and trigger a state update after a note is deleted like this :
export default function Home(notes) {
const [notesData, setNotesData] = useState(notes);
const deleteNote = async (note) => {
const res = await fetch(`http://localhost:3000/api/${note}`, {
method: "DELETE",
});
};
return (
<div>
<h1>Notes:</h1>
{notesData.notes.map((note) => {
return (
<div className="flex">
<p>{note.title}</p>
<p onClick={() => deleteNote(note.title).then(()=>{
const res = await fetch(`http://localhost:3000/api`);
const { data } = await res.json();
setNotesData(data)
})
}>Delete</p>
</div>
);
})}
</div>
);
}
export async function getServerSideProps() {
const res = await fetch(`http://localhost:3000/api`);
const { data } = await res.json();
return { props: { notes: data } };
}

Syntax Error: Invalid number, expected digit but got: "t". while passing a slug url to the graphql query function (nextjs app)

I'm having this error while I'm trying to get the right content according to the url. This is my query function:
const getSlugQuery = (slug) => {
const SLUG_QUERY = gql`
query ($slug: String!) {
postCollection(where:{slug:${slug}}) {
items {
title
shortDescription
heroImg {
url
}
createdAt
slug
}
}
}
`;
return SLUG_QUERY;
};
my getStaticprops where I pass the context.params.id:
export const getStaticProps = async (context) => {
const apolloClient = initializeApollo();
const { data } = await apolloClient.query({
query: getSlugQuery(context.params.id)
});
and the getStaticPath to prerender the cases:
export async function getStaticPaths() {
const apolloClient = initializeApollo();
const { data } = await apolloClient.query({
query: POSTS_QUERY
});
const paths = data.postCollection.items.map((post) => ({
params: { id: post.slug },
}))
return { paths, fallback: false }
}
If I try to pass an hardcoded url to the query, the response is working. What am I doing wrong there?
thanks
I believe you need to change your implementation to pass variables
Change getSlugQuery to not take any parameters:
const getSlugQuery = () => {
const SLUG_QUERY = gql`
query ($slug: String!) {
postCollection(where:{slug:$slug}) {
items {
title
shortDescription
heroImg {
url
}
createdAt
slug
}
}
}
`;
return SLUG_QUERY;
};
Then change getStaticProps to pass the slug as a variable to the apolloclient:
export const getStaticProps = async (context) => {
const apolloClient = initializeApollo();
const { data } = await apolloClient.query({
query: getSlugQuery(),
variables: {
slug: context.params.id,
},
});
};

Error: A required parameter (slug) was not provided as a string in getStaticPaths for /posts/[slug]

I have the following [slug].js file in my project:
import Head from "next/head";
import PostContent from "../../components/posts/post-detail/post-content";
import { getPostByName, getAllPosts } from "../../helpers/api-util";
function PostDetailPage(props) {
const post = props.selectedPost;
console.log(post);
if (!post) {
return (
<div className="">
<p>Loading...</p>
</div>
);
}
return <PostContent post={post.slug} />;
}
export async function getStaticProps(context) {
const blogSlug = context.params.slug;
const post = await getPostByName(blogSlug);
return {
props: {
selectedPost: post,
}, // will be passed to the page component as props
};
}
export async function getStaticPaths() {
const posts = await getAllPosts();
const paths = posts.map(post => ({ params: { blogSlug: post.slug } }));
return {
paths: paths,
fallback: "blocking",
};
}
export default PostDetailPage;
This is my file structure:
I am getting my data from firebase with the following data structure:
The idea is that when I click my post on the 'all posts' page, I get into the PostContent component that contains all my post info.
Once I try to click on a particular post, I am getting the error mentioned in the subject.
Slug is not a string so I am not entirely sure why I am getting this.
Thanks
You have mismatch between filename dynamic key and what you expect in the code.
You return blogSlug key in getStaticPaths:
const paths = posts.map(post => ({ params: { blogSlug: post.slug } }));
but your file is named [slug].js and you expect a slug key here in getStaticProps:
const blogSlug = context.params.slug;
It should be consistent, in this case it should be named slug everywhere.

Resources