i lost hours and a little of my sanity trying to solve this, but with no luck, despite all the things i've tried on the way.
So i have this code `
import { request } from "graphql-request";
import Link from "next/link";
import { useState } from "react";
import useSWR from "swr";
const fetcher = (endpoint, query, variables) => request(endpoint, query, variables);
export const getStaticProps = async () => {
const data = await fetcher(
"https://api-eu-central-1-shared-euc1-02.hygraph.com/v2/clh4qcnhy5i5r01um1qbo28dj/master",
`query getPosts {
postsConnection(orderBy: date_DESC, first: 2, skip: 0) {
edges {
node {
id
title
date
slug
description
author {
name
}
}
}
pageInfo {
hasNextPage
hasPreviousPage
pageSize
}
}
}`,
);
return {
props: {
posts: data,
},
};
};
export default function BlogPage({ posts }) {
console.log(posts);
const [searchValue, setSearchValue] = useState("");
const [skip, setSkip] = useState(0);
const { data, error } = useSWR(
[
"https://api-eu-central-1-shared-euc1-02.hygraph.com/v2/clh4qcnhy5i5r01um1qbo28dj/master",
`query getPosts($searchValue: String $skip: Int) {
postsConnection(orderBy: date_DESC, where: {title_contains: $searchValue}, first: 2, skip: $skip) {
edges {
node {
id
title
date
slug
description
id
author {
name
}
}
}
pageInfo{
hasNextPage
hasPreviousPage
pageSize
}
}
}
`,
searchValue,
skip,
],
(endpoint, query) => fetcher(endpoint, query, { searchValue, skip }),
{ initialData: posts, revalidateOnFocus: true },
);
if (error) {
return (
<div>
<h2>There was an error with the data fetching</h2>
</div>
);
}
return (
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-0">
<h1 className="text-5xl text-gray-600 font-serif mb-6 font-bold">The Blog</h1>
<div>
<input
type="text"
value={searchValue}
placeholder="Search blog posts"
className="focus:outline-none mb-6 focus:ring-2 focus:ring-gray-900 w-full rounded-lg border h-10 pl-4 text-lg text-gray-800 border-gray-200"
onChange={(event) => setSearchValue(event.target.value)}
/>
</div>
<div>
{data.postsConnection?.edges?.map((post) => (
<div key={post.node.slug} className="grid grid-cols-1 md:grid-cols-4 py-6">
<div className="mb-2 md:mb-0 md:col-span-1">
<p className="text-gray-600 text-sm">{new Date(post.node.date).toDateString()}</p>
</div>
<div className="md:col-span-3">
<Link href={`/blog/${post.node.slug}`}>
<a className="text-2xl font-semibold text-gray-900 hover:text-gray-700 transition-colors duration-300">
{post.node.title}
</a>
</Link>
<p className="text-gray-700 leading-relaxed">{post.node.description}</p>
<div className="text-sm text-gray-900 font-semibold mt-1">
{post.node.author.name}
</div>
</div>
</div>
))}
</div>
<div className="flex space-x-5 justify-center items-center mt-10">
<div>
<button
onClick={() => {
setSkip(skip - 2);
}}
disabled={!data.postsConnection.pageInfo.hasPreviousPage}
className="bg-indigo-700 w-20 text-white px-3 py-1 rounded-md disabled:bg-gray-400 disabled:text-gray-800">
Previous
</button>
</div>
<div>
<button
onClick={() => {
setSkip(skip + 2);
}}
disabled={!data.postsConnection.pageInfo.hasNextPage}
className="bg-indigo-700 w-20 text-white px-3 py-1 rounded-md disabled:bg-gray-400 disabled:text-gray-800">
Next
</button>
</div>
<div className="text-gray-700">Total Pages: {data.postsConnection.pageInfo.pageSize}</div>
</div>
</div>
);
}
and it throws an error
TypeError: Cannot read properties of undefined (reading 'postsConnection')
Source
pages/blog/index.js (105:14) @ BlogPage
103 | </div>
104 | <div>
> 105 | {data.postsConnection?.edges?.map((post) => (
| ^
106 | <div key={post.node.slug} className="grid grid-cols-1 md:grid-cols-4 py-6">
107 | <div className="mb-2 md:mb-0 md:col-span-1">
108 | <p className="text-gray-600 text-sm">{new Date(post.node.date).toDateString()}</p>`
When i query the graphQL directly with the query's on the code, all goes well and here is the result of those querys, getStaticProps query `
{
"data": {
"postsConnection": {
"edges": [
{
"node": {
"id": "clh4w8dhkaufl0bw1jux7ek2y",
"title": "React Toast Component and Custom Hook using Tailwindcss",
"date": "2023-05-01T13:45:00+00:00",
"slug": "react-toast-component-and-custom-hook-using-tailwindcss",
"description": "Toasts are basically just notifications. When you have a complex application or you need a lot of input",
"author": {
"name": "HerminioHenriques"
}
}
},
{
"node": {
"id": "clh4tgvgxac9f0bt92iyuni90",
"title": "Dummy markdown post",
"date": "2023-05-01T12:26:00+00:00",
"slug": "dummy-markdown-post",
"description": "How to use markdown language",
"author": {
"name": "HerminioHenriques"
}
}
},
{
"node": {
"id": "clh4var6yaqwl0bw1aefk73rc",
"title": "Next.js, Typescript and ESLint Starter Configuration",
"date": "2023-04-25T17:00:00+00:00",
"slug": "nextjs-typescript-and-eslint-starter-configuration",
"description": "This blog post will guide you through configuring a new Next.js project, ready to go with Typescript, ESLint and pre-commit checking with Husky",
"author": {
"name": "HerminioHenriques"
}
}
}
],
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"pageSize": 3
}
}
}
}
and BlogPage query
{
"data": {
"postsConnection": {
"edges": [
{
"node": {
"id": "clh4tgvgxac9f0bt92iyuni90",
"title": "Dummy markdown post",
"date": "2023-05-01T12:26:00+00:00",
"slug": "dummy-markdown-post",
"description": "How to use markdown language",
"author": {
"name": "HerminioHenriques"
}
}
}
],
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"pageSize": 1
}
}
}
}
I just can't understand why i'm not getting my data variable populated and with no data the posts props passed on the BlogPage is undefined, can anyone please help me?
swr is a hook. data
will be undefined until the query completes. While data
is undefined you can return a loading component (typically a spinner).
const { data, error } = useSWR(…);
if (error) return (
<div>
<h2>There was an error with the data fetching</h2>
</div>
);
else if (data) return (…your markup…);
else return <Loading />;