@@ -2,7 +2,7 @@ import { gql, useQuery } from "@apollo/client";
22import { getNextStaticProps } from "@faustwp/core" ;
33import { ArrowPathIcon , ChevronDownIcon } from "@heroicons/react/24/outline" ;
44import Link from "next/link" ;
5- import { useState , useEffect } from "react" ;
5+ import { useState } from "react" ;
66import Card from "@/components/card" ;
77import Date from "@/components/date" ;
88import Seo from "@/components/seo" ;
@@ -16,6 +16,7 @@ const GET_POSTS = gql`
1616 }
1717 edges {
1818 node {
19+ id
1920 title
2021 excerpt
2122 date
@@ -29,28 +30,18 @@ const GET_POSTS = gql`
2930
3031const BATCH_SIZE = 12 ;
3132export default function BlogIndex ( ) {
32- const { data, loading, error, fetchMore } = useQuery ( GET_POSTS , {
33- variables : { first : BATCH_SIZE , after : undefined } ,
33+ const {
34+ data,
35+ loading = true ,
36+ error,
37+ fetchMore,
38+ } = useQuery ( GET_POSTS , {
39+ // eslint-disable-next-line unicorn/no-null
40+ variables : { first : BATCH_SIZE , after : null } ,
3441 notifyOnNetworkStatusChange : true ,
3542 fetchPolicy : "cache-and-network" ,
3643 } ) ;
3744
38- const [ posts , setPosts ] = useState ( [ ] ) ;
39- const [ loadingMore , setLoadingMore ] = useState ( false ) ;
40- const [ cursor , setCursor ] = useState ( false ) ;
41- const [ hasMorePosts , setHasMorePosts ] = useState ( true ) ;
42-
43- useEffect ( ( ) => {
44- if ( data ) {
45- setPosts ( ( previousPosts ) => [
46- ...previousPosts ,
47- ...data . posts . edges . map ( ( edge ) => edge . node ) ,
48- ] ) ;
49- setCursor ( data . posts . pageInfo . endCursor ) ;
50- setHasMorePosts ( data . posts . pageInfo . hasNextPage ) ;
51- }
52- } , [ data ] ) ;
53-
5445 if ( loading && ! data )
5546 return (
5647 < div className = "container-main flex justify-center py-20" >
@@ -65,21 +56,12 @@ export default function BlogIndex() {
6556 }
6657
6758 const loadMorePosts = async ( ) => {
68- setLoadingMore ( true ) ;
69- const { data : moreData } = await fetchMore ( {
59+ await fetchMore ( {
7060 variables : {
7161 first : BATCH_SIZE ,
72- after : cursor ,
62+ after : data . posts . pageInfo . endCursor ,
7363 } ,
7464 } ) ;
75-
76- setPosts ( ( previousPosts ) => [
77- ...previousPosts ,
78- ...moreData . posts . edges . map ( ( edge ) => edge . node ) ,
79- ] ) ;
80- setCursor ( moreData . posts . pageInfo . endCursor ) ;
81- setHasMorePosts ( moreData . posts . pageInfo . hasNextPage ) ;
82- setLoadingMore ( false ) ;
8365 } ;
8466
8567 return (
@@ -96,7 +78,7 @@ export default function BlogIndex() {
9678 Faust.js news
9779 </ h1 >
9880 < ul className = "mt-8 grid list-none auto-rows-max grid-cols-6 gap-4 pl-0 md:grid-cols-12 md:gap-6 xl:gap-8" >
99- { posts . map ( ( post ) => (
81+ { data . posts . edges . map ( ( { node : post } ) => (
10082 < Card
10183 as = "li"
10284 className = "group relative col-span-full flex flex-col rounded-2xl p-4 shadow-gray-900 transition duration-100 hover:bg-gray-900 hover:shadow-xl hover:ring-blue-600/40 md:col-span-6 md:p-6 lg:col-span-4 lg:p-8"
@@ -119,30 +101,54 @@ export default function BlogIndex() {
119101 </ Card >
120102 ) ) }
121103 </ ul >
122- { hasMorePosts && (
104+ { data . posts . pageInfo . hasNextPage && (
123105 < div className = "mt-8 flex justify-center" >
124- < button
125- type = "button"
126- className = "flex cursor-pointer items-center rounded-sm bg-purple-700 px-4 py-2 text-white transition ease-in-out hover:bg-purple-800"
127- onClick = { loadMorePosts }
128- disabled = { loadingMore }
129- >
130- { loadingMore ? (
131- < >
132- Loading < ArrowPathIcon className = "ml-2 h-5 w-5 animate-spin" />
133- </ >
134- ) : (
135- < >
136- Load more < ChevronDownIcon className = "ml-2 h-5 w-5" />
137- </ >
138- ) }
139- </ button >
106+ < LoadMoreButton onClick = { loadMorePosts } />
140107 </ div >
141108 ) }
142109 </ main >
143110 ) ;
144111}
145112
113+ const LoadMoreButton = ( { onClick } ) => {
114+ const [ loading , setLoading ] = useState ( false ) ;
115+
116+ const handleLoadMore = async ( ) => {
117+ setLoading ( true ) ;
118+ await onClick ( ) ;
119+ setLoading ( false ) ;
120+ } ;
121+
122+ return (
123+ < button
124+ type = "button"
125+ className = "flex cursor-pointer items-center rounded-sm bg-purple-700 px-4 py-2 text-white transition ease-in-out hover:bg-purple-800"
126+ onClick = { handleLoadMore }
127+ disabled = { loading }
128+ >
129+ { loading ? (
130+ < >
131+ Loading < ArrowPathIcon className = "ml-2 h-5 w-5 animate-spin" />
132+ </ >
133+ ) : (
134+ < >
135+ Load more < ChevronDownIcon className = "ml-2 h-5 w-5" />
136+ </ >
137+ ) }
138+ </ button >
139+ ) ;
140+ } ;
141+
142+ BlogIndex . query = GET_POSTS ;
143+
144+ BlogIndex . variables = ( ) => {
145+ return {
146+ // eslint-disable-next-line unicorn/no-null
147+ after : null ,
148+ first : BATCH_SIZE ,
149+ } ;
150+ } ;
151+
146152export async function getStaticProps ( context ) {
147153 return getNextStaticProps ( context , {
148154 Page : BlogIndex ,
0 commit comments