1
1
import { NextPage } from "next" ;
2
- import { useEffect , useState } from "react" ;
2
+ import { useCallback , useEffect , useRef , useState } from "react" ;
3
3
import Post from "../components/blog/post" ;
4
4
import { BlogPostsResponse } from "../types/blogPostsResponse" ;
5
5
import Head from "next/head" ;
6
6
import Container from "../components/uiLibrary/container" ;
7
+ import { BlogPost } from "../types/blogPost" ;
8
+ import Spinner from "../components/uiLibrary/spinner" ;
7
9
8
10
9
11
const Blog : NextPage = ( ) => {
10
- const [ posts , setPosts ] = useState ( { } as BlogPostsResponse ) ;
11
- const [ currentPage , setCurrentPage ] = useState ( 1 ) ;
12
+ const [ postsResponse , setPostsResponse ] = useState < BlogPostsResponse > ( ) ;
13
+ const [ posts , setPosts ] = useState < BlogPost [ ] > ( [ ] ) ;
12
14
const [ loading , setLoading ] = useState ( true ) ;
15
+ const INITIAL_PAGE = "https://changelog.unitystation.org/posts/?page=1" ;
16
+
17
+ const fetchPosts = async ( url : string ) : Promise < BlogPostsResponse > => {
18
+ setLoading ( true ) ;
19
+ const response = await fetch ( url ) ;
20
+ return await response . json ( ) ;
21
+ } ;
22
+
23
+ useEffect ( ( ) => {
24
+ fetchPosts ( INITIAL_PAGE )
25
+ . then ( json => {
26
+ setPostsResponse ( json ) ;
27
+ setPosts ( json . results ) ;
28
+ } )
29
+ . finally ( ( ) => setLoading ( false ) ) ;
30
+ } , [ ] ) ;
31
+
32
+ const handleScroll = useCallback ( async ( ) => {
33
+ if ( window . innerHeight + document . documentElement . scrollTop !== document . documentElement . offsetHeight || ! postsResponse ?. next ) return ;
34
+ setLoading ( true ) ;
35
+
36
+ const json = await fetchPosts ( postsResponse . next ) ;
37
+
38
+ setPosts ( ( prevPosts ) => [ ...prevPosts , ...json . results ] ) ;
39
+ setPostsResponse ( json ) ;
40
+
41
+ setLoading ( false ) ;
42
+ } , [ postsResponse ] ) ;
13
43
14
44
useEffect ( ( ) => {
15
- fetch ( `https://changelog.unitystation.org/posts` )
16
- . then ( response => response . json ( ) )
17
- . then ( json => setPosts ( json ) )
18
- . then ( ( ) => setLoading ( false ) )
19
- } , [ currentPage ] ) ;
45
+ window . addEventListener ( 'scroll' , handleScroll ) ;
46
+ return ( ) => window . removeEventListener ( 'scroll' , handleScroll ) ;
47
+ } , [ handleScroll ] ) ;
20
48
21
49
return (
22
50
< >
@@ -39,8 +67,9 @@ const Blog: NextPage = () => {
39
67
/>
40
68
</ Head >
41
69
< Container >
42
- { ! loading && < div >
43
- { posts . results . map ( ( post ) => {
70
+ < ul id = "posts" >
71
+ { posts &&
72
+ posts . map ( ( post ) => {
44
73
return (
45
74
< Post
46
75
key = { post . slug }
@@ -52,9 +81,10 @@ const Blog: NextPage = () => {
52
81
state = { post . state }
53
82
type = { post . type }
54
83
/>
55
- )
84
+ ) ;
56
85
} ) }
57
- </ div > }
86
+ </ ul >
87
+ { loading && < Spinner /> }
58
88
</ Container >
59
89
</ >
60
90
)
0 commit comments