|
|
@@ -1,8 +1,8 @@ |
|
|
|
import axios from 'axios' |
|
|
|
import toCamel from 'camelcase-keys' |
|
|
|
import { useEffect, useRef, useState } from 'react' |
|
|
|
import { useEffect, useLayoutEffect, useRef, useState } from 'react' |
|
|
|
import { Helmet } from 'react-helmet-async' |
|
|
|
import { Link, useLocation } from 'react-router-dom' |
|
|
|
import { Link, useLocation, useNavigationType } from 'react-router-dom' |
|
|
|
|
|
|
|
import PostList from '@/components/PostList' |
|
|
|
import TagSidebar from '@/components/TagSidebar' |
|
|
@@ -15,23 +15,29 @@ import type { Post, WikiPage } from '@/types' |
|
|
|
|
|
|
|
|
|
|
|
export default () => { |
|
|
|
const navigationType = useNavigationType () |
|
|
|
|
|
|
|
const containerRef = useRef<HTMLDivElement | null> (null) |
|
|
|
const loaderRef = useRef<HTMLDivElement | null> (null) |
|
|
|
|
|
|
|
const [cursor, setCursor] = useState ('') |
|
|
|
const [loading, setLoading] = useState (false) |
|
|
|
const [posts, setPosts] = useState<Post[]> ([]) |
|
|
|
const [wikiPage, setWikiPage] = useState<WikiPage | null> (null) |
|
|
|
|
|
|
|
const loaderRef = useRef<HTMLDivElement | null> (null) |
|
|
|
|
|
|
|
const loadMore = async (withCursor: boolean) => { |
|
|
|
setLoading (true) |
|
|
|
|
|
|
|
const res = await axios.get (`${ API_BASE_URL }/posts`, { |
|
|
|
params: { tags: tags.join (' '), |
|
|
|
match: anyFlg ? 'any' : 'all', |
|
|
|
...(withCursor ? { cursor } : { }) } }) |
|
|
|
limit: '20', |
|
|
|
...(withCursor && { cursor }) } }) |
|
|
|
const data = toCamel (res.data as any, { deep: true }) as { posts: Post[] |
|
|
|
nextCursor: string } |
|
|
|
setPosts (posts => [...(withCursor ? posts : []), ...data.posts]) |
|
|
|
setCursor (data.nextCursor) |
|
|
|
|
|
|
|
setLoading (false) |
|
|
|
} |
|
|
|
|
|
|
@@ -55,9 +61,25 @@ export default () => { |
|
|
|
} |
|
|
|
}, [loaderRef, loading]) |
|
|
|
|
|
|
|
useEffect (() => { |
|
|
|
setPosts ([]) |
|
|
|
loadMore (false) |
|
|
|
useLayoutEffect (() => { |
|
|
|
const savedState = sessionStorage.getItem ('posts') |
|
|
|
if (savedState && navigationType === 'POP') |
|
|
|
{ |
|
|
|
const { posts, cursor, scroll } = JSON.parse (savedState) |
|
|
|
setPosts (posts) |
|
|
|
setCursor (cursor) |
|
|
|
|
|
|
|
if (containerRef.current) |
|
|
|
containerRef.current.scrollTop = scroll |
|
|
|
|
|
|
|
loadMore (true) |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
setPosts ([]) |
|
|
|
loadMore (false) |
|
|
|
} |
|
|
|
sessionStorage.removeItem ('posts') |
|
|
|
|
|
|
|
setWikiPage (null) |
|
|
|
if (tags.length === 1) |
|
|
@@ -78,7 +100,7 @@ export default () => { |
|
|
|
}, [location.search]) |
|
|
|
|
|
|
|
return ( |
|
|
|
<div className="md:flex md:flex-1"> |
|
|
|
<div className="md:flex md:flex-1" ref={containerRef}> |
|
|
|
<Helmet> |
|
|
|
<title> |
|
|
|
{tags.length |
|
|
@@ -93,7 +115,13 @@ export default () => { |
|
|
|
<TabGroup> |
|
|
|
<Tab name="広場"> |
|
|
|
{posts.length |
|
|
|
? <PostList posts={posts} /> |
|
|
|
? ( |
|
|
|
<PostList posts={posts} onClick={() => { |
|
|
|
const statesToSave = { |
|
|
|
posts, cursor, |
|
|
|
scroll: containerRef.current?.scrollTop ?? 0 } |
|
|
|
sessionStorage.setItem ('posts', JSON.stringify (statesToSave)) |
|
|
|
}} />) |
|
|
|
: !(loading) && '広場には何もありませんよ.'} |
|
|
|
{loading && 'Loading...'} |
|
|
|
<div ref={loaderRef} className="h-12"></div> |
|
|
|