From 561c2e9bd5d34a339593c159698eeca5891b3b16 Mon Sep 17 00:00:00 2001 From: Innei Date: Fri, 23 Jun 2023 00:28:17 +0800 Subject: [PATCH] refactor: use jotai to holder data Signed-off-by: Innei --- src/app/notes/[id]/layout.tsx | 5 +- src/app/notes/[id]/page.tsx | 120 +++++++++++------- .../widgets/note/NoteActionAside.tsx | 64 +++------- .../widgets/note/NoteFooterNavigation.tsx | 14 +- .../widgets/note/NoteHideIfSecret.tsx | 22 ++-- src/components/widgets/note/NoteMetaBar.tsx | 26 ++-- src/components/widgets/note/NoteTimeline.tsx | 5 +- src/components/widgets/note/NoteTopic.tsx | 7 +- .../widgets/note/NoteTopicDetail.tsx | 10 +- src/components/widgets/note/NoteTopicInfo.tsx | 19 ++- .../widgets/post/PostActionAside.tsx | 6 +- src/components/widgets/subscribe/hooks.tsx | 2 + src/components/widgets/xlog/XLogInfo.tsx | 10 +- src/components/widgets/xlog/XLogSummary.tsx | 6 +- src/hooks/data/use-note.ts | 37 +----- src/providers/note/CurrentNodeData.tsx | 29 ----- .../note/CurrentNodeDataProvider.tsx | 52 ++++++++ 17 files changed, 214 insertions(+), 220 deletions(-) delete mode 100644 src/providers/note/CurrentNodeData.tsx create mode 100644 src/providers/note/CurrentNodeDataProvider.tsx diff --git a/src/app/notes/[id]/layout.tsx b/src/app/notes/[id]/layout.tsx index 7637456c34..b0558bf88a 100644 --- a/src/app/notes/[id]/layout.tsx +++ b/src/app/notes/[id]/layout.tsx @@ -1,11 +1,11 @@ import { headers } from 'next/dist/client/components/headers' import type { Metadata } from 'next' -import { QueryHydration } from '~/components/common/QueryHydration' import { BottomToUpTransitionView } from '~/components/ui/transition/BottomToUpTransitionView' import { REQUEST_QUERY } from '~/constants/system' import { attachUA } from '~/lib/attach-ua' import { getSummaryFromMd } from '~/lib/markdown' +import { CurrentNoteDataProvider } from '~/providers/note/CurrentNodeDataProvider' import { CurrentNoteIdProvider } from '~/providers/note/CurrentNoteIdProvider' import { queries } from '~/queries/definition' import { getQueryClient } from '~/utils/query-client.server' @@ -71,9 +71,8 @@ export default async ( return ( <> - {/* */} + - {props.children} diff --git a/src/app/notes/[id]/page.tsx b/src/app/notes/[id]/page.tsx index 9bb38ca098..e2c324c325 100644 --- a/src/app/notes/[id]/page.tsx +++ b/src/app/notes/[id]/page.tsx @@ -7,20 +7,21 @@ import { Balancer } from 'react-wrap-balancer' import clsx from 'clsx' import dayjs from 'dayjs' import dynamic from 'next/dynamic' -import type { Image, NoteModel } from '@mx-space/api-client' +import type { Image } from '@mx-space/api-client' import type { MarkdownToJSX } from '~/components/ui/markdown' +import type { PropsWithChildren } from 'react' import { BanCopyWrapper } from '~/components/common/BanCopyWrapper' import { ClientOnly } from '~/components/common/ClientOnly' import { MdiClockOutline } from '~/components/icons/clock' import { useSetHeaderMetaInfo } from '~/components/layout/header/hooks' import { FloatPopover } from '~/components/ui/float-popover' -import { Loading } from '~/components/ui/loading' import { Markdown } from '~/components/ui/markdown' import { XLogInfoForNote, XLogSummaryForNote } from '~/components/widgets/xlog' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { noopArr } from '~/lib/noop' import { MarkdownImageRecordProvider } from '~/providers/article/MarkdownImageRecordProvider' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' +import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider' import { LayoutRightSidePortal } from '~/providers/shared/LayoutRightSideProvider' import { WrappedElementProvider } from '~/providers/shared/WrappedElementProvider' import { parseDate } from '~/utils/datetime' @@ -59,33 +60,76 @@ const TocAutoScroll = dynamic(() => ) const PageImpl = () => { - const note = useCurrentNoteData() + return ( + <> + + + + ) +} +const NoteHeaderMetaInfoSetting = () => { const setHeaderMetaInfo = useSetHeaderMetaInfo() - useEffect(() => { - if (!note?.title) return - setHeaderMetaInfo({ + const meta = useCurrentNoteDataSelector((data) => { + if (!data) return null + const note = data.data + + return { title: note?.title, description: `手记${note.topic?.name ? ` / ${note.topic?.name}` : ''}`, slug: note?.nid.toString(), - }) - }, [note?.nid, note?.title, note?.topic?.name]) + } + }) - if (!note) { - return - } + useEffect(() => { + if (meta) setHeaderMetaInfo(meta) + }, [meta]) - // return null - return + return null } -const NotePage = memo(({ note }: { note: NoteModel }) => { - const tips = `创建于 ${parseDate(note.created, 'YYYY 年 M 月 D 日 dddd')}${ - note.modified - ? `,修改于 ${parseDate(note.modified, 'YYYY 年 M 月 D 日 dddd')}` +const NoteHeaderDate = () => { + const date = useCurrentNoteDataSelector((data) => ({ + created: data?.data.created, + modified: data?.data.modified, + })) + if (!date?.created) return null + + const tips = `创建于 ${parseDate(date.created, 'YYYY 年 M 月 D 日 dddd')}${ + date.modified + ? `,修改于 ${parseDate(date.modified, 'YYYY 年 M 月 D 日 dddd')}` : '' }` + return ( + + {tips} + + ) +} + +const NoteMarkdown = () => { + const text = useCurrentNoteDataSelector((data) => data?.data.text) + if (!text) return null + + return +} +const NoteMarkdownImageRecordProvider = (props: PropsWithChildren) => { + const images = useCurrentNoteDataSelector( + (data) => data?.data.images || (noopArr as Image[]), + ) + if (!images) return null + + return ( + + {props.children} + + ) +} +const NotePage = memo(() => { + const noteId = useCurrentNoteId() + if (!noteId) return null + return (
{
- - {tips} - + @@ -111,17 +153,11 @@ const NotePage = memo(({ note }: { note: NoteModel }) => { - + - + - + {
- + - +
) }) const NoteTitle = () => { - const note = useCurrentNoteData() - if (!note) return null - const title = note.title + const title = useCurrentNoteDataSelector((data) => data?.data.title) + if (!title) return null return (

{title} @@ -157,10 +192,9 @@ const NoteTitle = () => { } const NoteDateMeta = () => { - const note = useCurrentNoteData() - if (!note) return null - - const dateFormat = dayjs(note.created) + const created = useCurrentNoteDataSelector((data) => data?.data.created) + if (!created) return null + const dateFormat = dayjs(created) .locale('zh-cn') .format('YYYY 年 M 月 D 日 dddd') @@ -187,11 +221,3 @@ const MarkdownRenderers: { [name: string]: Partial } = { } export default PageImpl -// export default PageDataHolder(PageImpl, () => { -// const { id } = useParams() as { id: string } - -// useEffect(() => { -// springScrollToTop() -// }, [id]) -// return useNoteByNidQuery(id) -// }) diff --git a/src/components/widgets/note/NoteActionAside.tsx b/src/components/widgets/note/NoteActionAside.tsx index 9ba6ccbc42..18edc5fea1 100644 --- a/src/components/widgets/note/NoteActionAside.tsx +++ b/src/components/widgets/note/NoteActionAside.tsx @@ -1,18 +1,19 @@ 'use client' -import { useQueryClient } from '@tanstack/react-query' import { motion, useAnimationControls, useForceUpdate } from 'framer-motion' -import { produce } from 'immer' -import type { NoteWrappedPayload } from '@mx-space/api-client' import { MotionButtonBase } from '~/components/ui/button' import { useIsClient } from '~/hooks/common/use-is-client' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { routeBuilder, Routes } from '~/lib/route-builder' import { toast } from '~/lib/toast' import { urlBuilder } from '~/lib/url-builder' +import { + getCurrentNoteData, + setCurrentNoteData, + useCurrentNoteDataSelector, +} from '~/providers/note/CurrentNodeDataProvider' +import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider' import { useAggregationData } from '~/providers/root/aggregation-data-provider' -import { queries } from '~/queries/definition' import { isLikedBefore, setLikeId } from '~/utils/cookie' import { clsxm } from '~/utils/helper' import { apiClient } from '~/utils/request' @@ -35,50 +36,20 @@ export const NoteActionAside: Component = ({ className }) => { } const LikeButton = () => { - const note = useCurrentNoteData() - - const queryClient = useQueryClient() const control = useAnimationControls() const [update] = useForceUpdate() - if (!note) return null - const id = note.id - const handleLike = () => { - // queryClient.setQueriesData( - // queries.note.byNid(note.nid.toString()), - // (old: any) => { - // // return produce(old as NoteWrappedPayload, (draft) => { - // // draft.data.count.like += 1 - // // draft - // // }) - // // old.data.count.like += 1 - // // old.data.count = { ...old.data.count } - // // old.data = { ...old.data } - // return { - // ...old, - // data: { - // ...old.data, - // text: `1${Math.random()}`, - // // count: { - // // ...old.data.count, - // // like: old.data.count.like + 1, - // // }, - // }, - // } - // }, - // ) - // return + const id = useCurrentNoteDataSelector((data) => data?.data.id) + const nid = useCurrentNoteId() + if (!id) return null + const handleLike = () => { if (isLikedBefore(id)) return + if (!nid) return apiClient.note.likeIt(id).then(() => { setLikeId(id) - queryClient.setQueriesData( - queries.note.byNid(note.nid.toString()), - (old: any) => { - return produce(old as NoteWrappedPayload, (draft) => { - draft.data.count.like += 1 - }) - }, - ) + setCurrentNoteData((draft) => { + draft.data.count.like += 1 + }) update() }) } @@ -138,10 +109,9 @@ const LikeButton = () => { const ShareButton = () => { const hasShare = 'share' in navigator const isClient = useIsClient() - const note = useCurrentNoteData() + const aggregation = useAggregationData() if (!isClient) return null - if (!note) return null if (!hasShare) { return null @@ -152,6 +122,10 @@ const ShareButton = () => { aria-label="Share This Note Button" className="flex flex-col space-y-2" onClick={() => { + const note = getCurrentNoteData()?.data + + if (!note) return + navigator.share({ title: note.title, text: note.text, diff --git a/src/components/widgets/note/NoteFooterNavigation.tsx b/src/components/widgets/note/NoteFooterNavigation.tsx index 1860dd751b..18171bfff9 100644 --- a/src/components/widgets/note/NoteFooterNavigation.tsx +++ b/src/components/widgets/note/NoteFooterNavigation.tsx @@ -7,17 +7,21 @@ import type { FC } from 'react' import { MdiClockTimeThreeOutline } from '~/components/icons/clock' import { Divider } from '~/components/ui/divider' import { OnlyMobile } from '~/components/ui/viewport/OnlyMobile' -import { useNoteByNidQuery } from '~/hooks/data/use-note' import { routeBuilder, Routes } from '~/lib/route-builder' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' import { springScrollToTop } from '~/utils/scroller' export const NoteFooterNavigation: FC<{ noteId: string }> = ({ noteId: id, }) => { - const { data } = useNoteByNidQuery(id, (data) => ({ - nextNid: data.next?.nid, - prevNid: data.prev?.nid, - })) + const data = useCurrentNoteDataSelector((data) => + !data + ? null + : { + nextNid: data?.next?.nid, + prevNid: data?.prev?.nid, + }, + ) const router = useRouter() diff --git a/src/components/widgets/note/NoteHideIfSecret.tsx b/src/components/widgets/note/NoteHideIfSecret.tsx index a26da7aeff..abbedc2711 100644 --- a/src/components/widgets/note/NoteHideIfSecret.tsx +++ b/src/components/widgets/note/NoteHideIfSecret.tsx @@ -6,20 +6,20 @@ import { useEffect, useMemo } from 'react' import dayjs from 'dayjs' import { useIsLogged } from '~/atoms/owner' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { toast } from '~/lib/toast' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' +import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider' export const NoteHideIfSecret: Component = ({ children }) => { - const note = useCurrentNoteData() - const secretDate = useMemo(() => new Date(note?.secret!), [note?.secret]) - const isSecret = note?.secret - ? dayjs(note?.secret).isAfter(new Date()) - : false + const noteSecret = useCurrentNoteDataSelector((data) => data?.data.secret) + const nodeId = useCurrentNoteId() + const secretDate = useMemo(() => new Date(noteSecret!), [noteSecret]) + const isSecret = noteSecret ? dayjs(noteSecret).isAfter(new Date()) : false const isLogged = useIsLogged() useEffect(() => { - if (!note?.id) return + if (!nodeId) return let timer: any const timeout = +secretDate - +new Date() // https://stackoverflow.com/questions/3468607/why-does-settimeout-break-for-large-millisecond-delay-values @@ -33,12 +33,12 @@ export const NoteHideIfSecret: Component = ({ children }) => { return () => { clearTimeout(timer) } - }, [isSecret, secretDate, note?.id]) + }, [isSecret, secretDate, nodeId]) - if (!note) return null + if (!nodeId) return null if (isSecret) { - const dateFormat = note.secret + const dateFormat = noteSecret ? Intl.DateTimeFormat('zh-cn', { hour12: false, hour: 'numeric', @@ -46,7 +46,7 @@ export const NoteHideIfSecret: Component = ({ children }) => { year: 'numeric', day: 'numeric', month: 'long', - }).format(new Date(note.secret)) + }).format(new Date(noteSecret)) : '' if (isLogged) { diff --git a/src/components/widgets/note/NoteMetaBar.tsx b/src/components/widgets/note/NoteMetaBar.tsx index dd047b20d8..4446b4b4e4 100644 --- a/src/components/widgets/note/NoteMetaBar.tsx +++ b/src/components/widgets/note/NoteMetaBar.tsx @@ -2,28 +2,26 @@ import { CreativeCommonsIcon } from '~/components/icons/cc' import { DividerVertical } from '~/components/ui/divider' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { mood2icon, weather2icon } from '~/lib/meta-icon' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' const dividerVertical = const sectionBlockClassName = 'flex items-center space-x-1 flex-shrink-0' export const NoteMetaBar = () => { - const note = useCurrentNoteData() - if (!note) return null - const { weather, mood, count } = note return ( <> - - - - + + + + ) } -export const NoteMetaWeather = ({ weather }: { weather?: string }) => { +export const NoteMetaWeather = () => { + const weather = useCurrentNoteDataSelector((data) => data?.data.weather) if (!weather) return null return ( <> @@ -36,7 +34,9 @@ export const NoteMetaWeather = ({ weather }: { weather?: string }) => { ) } -export const NoteMetaMood = ({ mood }: { mood?: string }) => { +export const NoteMetaMood = () => { + const mood = useCurrentNoteDataSelector((data) => data?.data.mood) + if (!mood) return null return ( <> @@ -49,7 +49,8 @@ export const NoteMetaMood = ({ mood }: { mood?: string }) => { ) } -export const NoteMetaReadCount = ({ read }: { read?: number }) => { +export const NoteMetaReadCount = () => { + const read = useCurrentNoteDataSelector((data) => data?.data.count.read) if (!read) return null return ( <> @@ -62,7 +63,8 @@ export const NoteMetaReadCount = ({ read }: { read?: number }) => { ) } -export const NoteMetaLikeCount = ({ like }: { like?: number }) => { +export const NoteMetaLikeCount = () => { + const like = useCurrentNoteDataSelector((data) => data?.data.count.like) if (!like) return null return ( <> diff --git a/src/components/widgets/note/NoteTimeline.tsx b/src/components/widgets/note/NoteTimeline.tsx index b2abf23955..f2c326269d 100644 --- a/src/components/widgets/note/NoteTimeline.tsx +++ b/src/components/widgets/note/NoteTimeline.tsx @@ -7,8 +7,8 @@ import Link from 'next/link' import { tv } from 'tailwind-variants' import { LeftToRightTransitionView } from '~/components/ui/transition/LeftToRightTransitionView' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { routeBuilder, Routes } from '~/lib/route-builder' +import { getCurrentNoteData } from '~/providers/note/CurrentNodeDataProvider' import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider' import { clsxm } from '~/utils/helper' import { apiClient } from '~/utils/request' @@ -20,7 +20,8 @@ export const NoteTimeline = () => { } const NoteTimelineImpl = () => { - const note = useCurrentNoteData() + void useCurrentNoteId() + const note = getCurrentNoteData()?.data const noteId = note?.id const { data: timelineData } = useQuery( diff --git a/src/components/widgets/note/NoteTopic.tsx b/src/components/widgets/note/NoteTopic.tsx index 0c89f23925..66b54b6a94 100644 --- a/src/components/widgets/note/NoteTopic.tsx +++ b/src/components/widgets/note/NoteTopic.tsx @@ -1,11 +1,11 @@ import Link from 'next/link' -import type { TopicModel } from '@mx-space/api-client' import type { FC } from 'react' import { Avatar } from '~/components/ui/avatar' import { Divider } from '~/components/ui/divider' import { FloatPopover } from '~/components/ui/float-popover' import { routeBuilder, Routes } from '~/lib/route-builder' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' import { NoteTopicDetail } from './NoteTopicDetail' import { NoteTopicMarkdownRender } from './NoteTopicMarkdownRender' @@ -19,8 +19,9 @@ const textToBigCharOrWord = (name: string | undefined) => { return bigChar } -export const NoteTopic: FC<{ topic?: TopicModel }> = (props) => { - const { topic } = props +export const NoteTopic: FC = () => { + const topic = useCurrentNoteDataSelector((state) => state?.data.topic) + if (!topic) return null const { icon, name, introduce } = topic diff --git a/src/components/widgets/note/NoteTopicDetail.tsx b/src/components/widgets/note/NoteTopicDetail.tsx index 99cf4246db..e5816ef080 100644 --- a/src/components/widgets/note/NoteTopicDetail.tsx +++ b/src/components/widgets/note/NoteTopicDetail.tsx @@ -11,8 +11,8 @@ import { Divider, DividerVertical } from '~/components/ui/divider' import { Loading } from '~/components/ui/loading' import { RelativeTime } from '~/components/ui/relative-time' import { useIsClient } from '~/hooks/common/use-is-client' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { routeBuilder, Routes } from '~/lib/route-builder' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' import { apiClient } from '~/utils/request' import { NoteTopicMarkdownRender } from './NoteTopicMarkdownRender' @@ -105,16 +105,16 @@ export const NoteTopicDetail: FC<{ topic: TopicModel }> = (props) => { } export const ToTopicLink: FC = () => { - const note = useCurrentNoteData() - if (!note?.topic) return null + const topic = useCurrentNoteDataSelector((data) => data?.data.topic) + if (!topic) return null return ( - {note.topic.name} + {topic.name} ) diff --git a/src/components/widgets/note/NoteTopicInfo.tsx b/src/components/widgets/note/NoteTopicInfo.tsx index 8cd8c5a97e..91f8f782a0 100644 --- a/src/components/widgets/note/NoteTopicInfo.tsx +++ b/src/components/widgets/note/NoteTopicInfo.tsx @@ -2,20 +2,19 @@ import { Divider } from '~/components/ui/divider' import { FloatPopover } from '~/components/ui/float-popover' -import { useCurrentNoteData } from '~/hooks/data/use-note' -import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' import { NoteTopicDetail, ToTopicLink } from './NoteTopicDetail' +// export const NoteTopicInfo = () => { +// const noteId = useCurrentNoteId() +// if (!noteId) return null +// return +// } export const NoteTopicInfo = () => { - const noteId = useCurrentNoteId() - if (!noteId) return null - return -} -const NoteTopicInfoImpl = () => { - const note = useCurrentNoteData() + const topic = useCurrentNoteDataSelector((data) => data?.data.topic) - if (!note?.topic) return null + if (!topic) return null return ( <> @@ -30,7 +29,7 @@ const NoteTopicInfoImpl = () => { wrapperClassNames="flex flex-grow flex-shrink min-w-0" TriggerComponent={ToTopicLink} > - + ) diff --git a/src/components/widgets/post/PostActionAside.tsx b/src/components/widgets/post/PostActionAside.tsx index d58d3c09d2..3a96b37d1e 100644 --- a/src/components/widgets/post/PostActionAside.tsx +++ b/src/components/widgets/post/PostActionAside.tsx @@ -8,11 +8,12 @@ import type { NoteWrappedPayload } from '@mx-space/api-client' import { IonThumbsup } from '~/components/icons/thumbs-up' import { MotionButtonBase } from '~/components/ui/button' import { useIsClient } from '~/hooks/common/use-is-client' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { useCurrentPostData } from '~/hooks/data/use-post' import { routeBuilder, Routes } from '~/lib/route-builder' import { toast } from '~/lib/toast' import { urlBuilder } from '~/lib/url-builder' +import { getCurrentNoteData } from '~/providers/note/CurrentNodeDataProvider' +import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider' import { useAggregationData } from '~/providers/root/aggregation-data-provider' import { queries } from '~/queries/definition' import { isLikedBefore, setLikeId } from '~/utils/cookie' @@ -113,7 +114,8 @@ const LikeButton = () => { const ShareButton = () => { const hasShare = 'share' in navigator const isClient = useIsClient() - const note = useCurrentNoteData() + void useCurrentNoteId() + const note = getCurrentNoteData()?.data const aggregation = useAggregationData() if (!isClient) return null if (!note) return null diff --git a/src/components/widgets/subscribe/hooks.tsx b/src/components/widgets/subscribe/hooks.tsx index cb6452546e..05c407a068 100644 --- a/src/components/widgets/subscribe/hooks.tsx +++ b/src/components/widgets/subscribe/hooks.tsx @@ -19,6 +19,8 @@ export const useIsEnableSubscribe = () => queryKey: SWR_CHECK_SUBSCRIBE_KEY, queryFn: apiClient.subscribe.check, select: (data: { enable: boolean }) => data?.enable, + cacheTime: 60_000 * 10, + staleTime: 60_000 * 10, }) export const usePresentSubscribeModal = ( diff --git a/src/components/widgets/xlog/XLogInfo.tsx b/src/components/widgets/xlog/XLogInfo.tsx index d784b03c8e..5c717e8894 100644 --- a/src/components/widgets/xlog/XLogInfo.tsx +++ b/src/components/widgets/xlog/XLogInfo.tsx @@ -5,8 +5,8 @@ import type { XLogMeta } from './types' import { Collapse } from '~/components/ui/collapse' import { useIsClient } from '~/hooks/common/use-is-client' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { useCurrentPostData } from '~/hooks/data/use-post' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' export const XLogInfoForPost: FC = () => { const data = useCurrentPostData() @@ -18,16 +18,12 @@ export const XLogInfoForPost: FC = () => { } export const XLogInfoForNote: FC = () => { - const data = useCurrentNoteData() - - if (!data) return null - - const meta = data.meta?.xLog + const meta = useCurrentNoteDataSelector((data) => data?.data.meta?.xLog) return } const XLogInfoBase: FC<{ - meta?: XLogMeta + meta?: XLogMeta | null }> = ({ meta }) => { const [collapse, setCollapse] = useState(false) diff --git a/src/components/widgets/xlog/XLogSummary.tsx b/src/components/widgets/xlog/XLogSummary.tsx index 59249e9b50..9defd05ba9 100644 --- a/src/components/widgets/xlog/XLogSummary.tsx +++ b/src/components/widgets/xlog/XLogSummary.tsx @@ -3,8 +3,8 @@ import type { FC, SVGProps } from 'react' import { AutoResizeHeight } from '~/components/common/AutoResizeHeight' import { useIsClient } from '~/hooks/common/use-is-client' -import { useCurrentNoteData } from '~/hooks/data/use-note' import { useCurrentPostData } from '~/hooks/data/use-post' +import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider' import { clsxm } from '~/utils/helper' import { apiClient } from '~/utils/request' @@ -81,8 +81,8 @@ export const XLogSummaryForPost: FC = () => { } export const XLogSummaryForNote: FC = () => { - const data = useCurrentNoteData() - const cid = data?.meta?.xLog?.cid + const cid = useCurrentNoteDataSelector((data) => data?.data.meta?.xLog?.cid) + if (!cid) return null return diff --git a/src/hooks/data/use-note.ts b/src/hooks/data/use-note.ts index eed64280f8..eadf3faca3 100644 --- a/src/hooks/data/use-note.ts +++ b/src/hooks/data/use-note.ts @@ -1,46 +1,11 @@ import { useQuery, useQueryClient } from '@tanstack/react-query' import { useMemo } from 'react' -import type { NoteModel, NoteWrappedPayload } from '@mx-space/api-client' +import type { NoteWrappedPayload } from '@mx-space/api-client' import type { UseQueryResult } from '@tanstack/react-query' -import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider' import { queries } from '~/queries/definition' import { isClientSide } from '~/utils/env' -export function useCurrentNoteData(): NoteModel -export function useCurrentNoteData( - select?: (data: NoteWrappedPayload) => T, -): T -export function useCurrentNoteData(select?: any) { - const nid = useCurrentNoteId() - - if (!nid) { - throw 'nid not ready' - } - - const searchParams = useMemo( - () => (isClientSide ? new URLSearchParams(location.search) : null), - [nid], - ) - const password = searchParams?.get('password') - const queryClient = useQueryClient() - const query = queries.note.byNid(nid, password!) - const key = query.queryKey - - const { data: noteAggregation } = useQuery({ - ...query, - // enabled: nid, - select(data) { - if (typeof select === 'function') return select(data) - return data.data - }, - initialData: queryClient.getQueryData(key), - keepPreviousData: true, - }) - - return noteAggregation -} - export function useNoteByNidQuery( nid: string, ): UseQueryResult diff --git a/src/providers/note/CurrentNodeData.tsx b/src/providers/note/CurrentNodeData.tsx deleted file mode 100644 index d6176d450c..0000000000 --- a/src/providers/note/CurrentNodeData.tsx +++ /dev/null @@ -1,29 +0,0 @@ -'use client' - -import { memo, useEffect } from 'react' -import { atom, useAtomValue } from 'jotai' -import type { NoteWrappedPayload } from '@mx-space/api-client' -import type { FC, PropsWithChildren } from 'react' - -import { useBeforeMounted } from '~/hooks/common/use-before-mounted' -import { jotaiStore } from '~/lib/store' - -const currentNoteDataAtom = atom(null) -export const CurrentNoteDataProvider: FC< - { - data: NoteWrappedPayload - } & PropsWithChildren -> = memo(({ data, children }) => { - useBeforeMounted(() => { - jotaiStore.set(currentNoteDataAtom, data) - }) - - useEffect(() => { - jotaiStore.set(currentNoteDataAtom, data) - }, [data]) - - return children -}) -export const useCurrentNoteData = () => { - return useAtomValue(currentNoteDataAtom) -} diff --git a/src/providers/note/CurrentNodeDataProvider.tsx b/src/providers/note/CurrentNodeDataProvider.tsx new file mode 100644 index 0000000000..58741b46cc --- /dev/null +++ b/src/providers/note/CurrentNodeDataProvider.tsx @@ -0,0 +1,52 @@ +'use client' + +import { memo, useCallback, useEffect } from 'react' +import { produce } from 'immer' +import { atom, useAtomValue } from 'jotai' +import { selectAtom } from 'jotai/utils' +import type { NoteWrappedPayload } from '@mx-space/api-client' +import type { FC, PropsWithChildren } from 'react' + +import { useBeforeMounted } from '~/hooks/common/use-before-mounted' +import { noopArr } from '~/lib/noop' +import { jotaiStore } from '~/lib/store' + +const currentNoteDataAtom = atom(null) +export const CurrentNoteDataProvider: FC< + { + data: NoteWrappedPayload + } & PropsWithChildren +> = memo(({ data, children }) => { + useBeforeMounted(() => { + jotaiStore.set(currentNoteDataAtom, data) + }) + + useEffect(() => { + jotaiStore.set(currentNoteDataAtom, data) + }, [data]) + + return children +}) +export const useCurrentNoteDataSelector = ( + selector: (data: NoteWrappedPayload | null) => T, + deps?: any[], +) => { + const nextSelector = useCallback((data: NoteWrappedPayload | null) => { + return data ? selector(data) : null + }, deps || noopArr) + + return useAtomValue(selectAtom(currentNoteDataAtom, nextSelector)) +} + +export const setCurrentNoteData = ( + recipe: (draft: NoteWrappedPayload) => void, +) => { + jotaiStore.set( + currentNoteDataAtom, + produce(jotaiStore.get(currentNoteDataAtom), recipe), + ) +} + +export const getCurrentNoteData = () => { + return jotaiStore.get(currentNoteDataAtom) +}