Skip to content

Commit 8c7dcce

Browse files
committed
fix(recently): event handler
Signed-off-by: Innei <tukon479@gmail.com>
1 parent 05871ed commit 8c7dcce

File tree

2 files changed

+97
-64
lines changed

2 files changed

+97
-64
lines changed

src/pages/_app.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { SWRConfig } from 'swr'
1313
import type { FullConfiguration } from 'swr/_internal'
1414

1515
import { NoDataErrorView } from '~/components/app/Error/no-data'
16+
import { ErrorBoundary } from '~/components/app/ErrorBoundary'
1617
import { BasicLayout } from '~/components/layouts/BasicLayout'
1718
import { DebugLayout } from '~/components/layouts/DebugLayout'
1819
import type { InitialDataType } from '~/context/initial-data'
@@ -82,7 +83,9 @@ const Wrapper = memo((props) => {
8283
<>
8384
<SWRConfig value={swrConfig.current}>
8485
<BasicLayout>
85-
<Content>{props.children}</Content>
86+
<Content>
87+
<ErrorBoundary>{props.children}</ErrorBoundary>
88+
</Content>
8689
</BasicLayout>
8790
</SWRConfig>
8891

@@ -112,7 +115,7 @@ App.getInitialProps = async (props: AppContext) => {
112115
// 这里抛出,和官网直接 await getProps 一样,异常走到 _error 处理
113116
throw e
114117
}
115-
// 这里捕获, 为了走全局无数据页
118+
// 这里捕获,为了走全局无数据页
116119
if (ctx.res) {
117120
ctx.res.statusCode = 466
118121
ctx.res.statusMessage = 'No Data'

src/pages/recently/index.tsx

Lines changed: 92 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
import { clsx } from 'clsx'
2+
import { uniqWith } from 'lodash-es'
23
import { observer } from 'mobx-react-lite'
34
import type { NextPage } from 'next'
4-
import { Fragment, useCallback, useEffect, useRef, useState } from 'react'
5+
import {
6+
Fragment,
7+
useCallback,
8+
useEffect,
9+
useMemo,
10+
useRef,
11+
useState,
12+
} from 'react'
513
import { useInView } from 'react-intersection-observer'
614
import { message } from 'react-message-popup'
715
import useSWR from 'swr'
@@ -30,19 +38,18 @@ import styles from './index.module.css'
3038

3139
const FETCH_SIZE = 10
3240

33-
const useDataEventHandler = (data, setData) => {
41+
const useDataEventHandler = () => {
42+
const [newData, setNewData] = useState<
43+
(RecentlyModel & { comments: number })[]
44+
>([])
45+
const [deleteIds, setDeleteIds] = useState<string[]>([])
3446
useEffect(() => {
3547
const create = (payload: RecentlyModel) => {
36-
data.unshift(payload)
37-
setData([...data])
48+
setNewData((data) => [{ ...payload, comments: 0 }, ...data])
3849
}
3950

4051
const del = ({ id }) => {
41-
const index = data.findIndex((d) => d.id === id)
42-
if (index != -1) {
43-
data.splice(index, 1)
44-
setData([...data])
45-
}
52+
setDeleteIds((ids) => [...ids, id])
4653
}
4754

4855
eventBus.on(EventTypes.RECENTLY_CREATE, create)
@@ -52,7 +59,9 @@ const useDataEventHandler = (data, setData) => {
5259
eventBus.off(EventTypes.RECENTLY_CREATE, create)
5360
eventBus.off(EventTypes.RECENTLY_DElETE, del)
5461
}
55-
}, [data])
62+
}, [])
63+
64+
return { newData, deleteIds: new Set(deleteIds) }
5665
}
5766

5867
const RecentlyPage: NextPage = () => {
@@ -74,31 +83,42 @@ const RecentlyPage: NextPage = () => {
7483
if (data.length < FETCH_SIZE) {
7584
setHasNext(false)
7685
}
77-
return data
86+
return [before || 'root', data] as const
7887
},
7988
{
80-
revalidateIfStale: false,
81-
revalidateOnFocus: false,
82-
refreshWhenOffline: false,
83-
refreshInterval: 0,
84-
refreshWhenHidden: false,
85-
revalidateOnReconnect: false,
89+
isPaused() {
90+
return !hasNext
91+
},
8692
},
8793
)
8894

89-
const [data, setData] = useState<(RecentlyModel & { comments?: number })[]>(
90-
[],
95+
const [slicedData, setSliceData] = useState<
96+
Record<string, (RecentlyModel & { comments?: number })[]>
97+
>({})
98+
const data = useMemo(
99+
() => [...Object.values(slicedData)].flat(1),
100+
[slicedData],
91101
)
92102

93103
useEffect(() => {
94104
if (!fetchedData) {
95105
return
96106
}
107+
const [key, data] = fetchedData
97108

98-
setData((d) => [...d, ...fetchedData])
109+
if (!data) {
110+
return
111+
}
112+
113+
setSliceData((d) => {
114+
return {
115+
...d,
116+
[key]: data,
117+
}
118+
})
99119
}, [fetchedData])
100120

101-
useDataEventHandler(data, setData)
121+
const { deleteIds, newData } = useDataEventHandler()
102122

103123
const { ref, inView } = useInView()
104124

@@ -152,53 +172,63 @@ const RecentlyPage: NextPage = () => {
152172
<Loading />
153173
) : (
154174
<Fragment>
155-
{data.length == 0 ? (
175+
{data.length == 0 && newData.length == 0 ? (
156176
<p className="text-center">这里还没有内容哦</p>
157177
) : (
158178
<div className={styles['bubble-list']}>
159-
{data.map((d) => (
160-
<Fragment key={d.id}>
161-
<div
162-
className={clsx(
163-
'bubble',
164-
isLogged ? 'from-me' : 'from-them',
165-
)}
166-
>
167-
<div className="overflow-hidden">
168-
<Markdown
169-
forceBlock
170-
value={d.content}
171-
wrapperProps={wrapperProps}
172-
/>
173-
{d.ref && <RefPreview refModel={d.ref} />}
174-
</div>
175-
176-
<div className="text-sm float-right mt-1 flex items-center">
177-
<button
178-
className="inline-flex items-center"
179-
onClick={() =>
180-
d.allowComment ? handleClickComment(d.id) : void 0
181-
}
179+
{uniqWith([...newData, ...data], (a, b) => a.id === b.id).map(
180+
(d) => {
181+
if (deleteIds.has(d.id)) {
182+
return null
183+
}
184+
return (
185+
<Fragment key={d.id}>
186+
<div
187+
className={clsx(
188+
'bubble',
189+
isLogged ? 'from-me' : 'from-them',
190+
)}
182191
>
183-
<FontistoComments className="ml-2 mr-1 opacity-80" />
184-
<span className="mr-2 opacity-80">
185-
{d.comments || 0}
186-
</span>
187-
</button>
188-
<RelativeTime date={d.created} />
189-
</div>
190-
191-
{isLogged && (
192-
<div className="del" onClick={() => handleDelete(d.id)}>
193-
<JamTrash className="mr-2" />
194-
删除
192+
<div className="overflow-hidden">
193+
<Markdown
194+
forceBlock
195+
value={d.content}
196+
wrapperProps={wrapperProps}
197+
/>
198+
{d.ref && <RefPreview refModel={d.ref} />}
199+
</div>
200+
201+
<div className="text-sm float-right mt-1 flex items-center">
202+
<button
203+
className="inline-flex items-center"
204+
onClick={() =>
205+
d.allowComment ? handleClickComment(d.id) : void 0
206+
}
207+
>
208+
<FontistoComments className="ml-2 mr-1 opacity-80" />
209+
<span className="mr-2 opacity-80">
210+
{d.comments || 0}
211+
</span>
212+
</button>
213+
<RelativeTime date={d.created} />
214+
</div>
215+
216+
{isLogged && (
217+
<div
218+
className="del"
219+
onClick={() => handleDelete(d.id)}
220+
>
221+
<JamTrash className="mr-2" />
222+
删除
223+
</div>
224+
)}
195225
</div>
196-
)}
197-
</div>
198226

199-
<div className="clear-both" />
200-
</Fragment>
201-
))}
227+
<div className="clear-both" />
228+
</Fragment>
229+
)
230+
},
231+
)}
202232
</div>
203233
)}
204234

0 commit comments

Comments
 (0)