From f0f529f2eefc58bd8ea1dd445b001a628c57ef83 Mon Sep 17 00:00:00 2001 From: Innei Date: Wed, 14 Jun 2023 00:04:19 +0800 Subject: [PATCH] perf: re-reduce router change re-render Signed-off-by: Innei --- src/app/notes/[id]/page.tsx | 13 +++++++++++ src/app/notes/layout.tsx | 29 ++++++++++++++----------- src/hooks/data/use-note.ts | 4 ++-- src/providers/note/note-id-provider.tsx | 7 ++++++ 4 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 src/providers/note/note-id-provider.tsx diff --git a/src/app/notes/[id]/page.tsx b/src/app/notes/[id]/page.tsx index 72a10f9268..b1d2633047 100644 --- a/src/app/notes/[id]/page.tsx +++ b/src/app/notes/[id]/page.tsx @@ -1,13 +1,16 @@ 'use client' +import { useRef } from 'react' import { useParams } from 'next/navigation' import { Toc, TocAutoScroll } from '~/components/widgets/toc' import { useNoteByNidQuery } from '~/hooks/data/use-note' import { PageDataHolder } from '~/lib/page-holder' import { ArticleElementProvider } from '~/providers/article/article-element-provider' +import { useSetNoteId } from '~/providers/note/note-id-provider' import { NoteLayoutRightSidePortal } from '~/providers/note/right-side-provider' import { parseMarkdown } from '~/remark' +import { isClientSide } from '~/utils/env' const PageImpl = () => { const { id } = useParams() as { id: string } @@ -15,6 +18,16 @@ const PageImpl = () => { const mardownResult = parseMarkdown(data?.data?.text ?? '') + // Why do this, I mean why do set NoteId to context, don't use `useParams().id` for children components. + // Because any router params or query changes, will cause components that use `useParams()` hook, this hook is a context hook, + // For example, `ComA` use `useParams()` just want to get value `id`, + // but if router params or query changes `page` params, will cause `CompA` re - render. + const setNoteId = useSetNoteId() + const onceRef = useRef(false) + if (isClientSide() && !onceRef.current) { + onceRef.current = true + setNoteId(id) + } return (
diff --git a/src/app/notes/layout.tsx b/src/app/notes/layout.tsx index c354fd9879..bb07aef900 100644 --- a/src/app/notes/layout.tsx +++ b/src/app/notes/layout.tsx @@ -1,25 +1,28 @@ import type { PropsWithChildren } from 'react' import { NoteLeftSidebar } from '~/components/widgets/note/NoteLeftSidebar' +import { NoteIdProvider } from '~/providers/note/note-id-provider' import { NoteLayoutRightSideProvider } from '~/providers/note/right-side-provider' import { clsxm } from '~/utils/helper' export default async (props: PropsWithChildren) => { return ( -
- + +
+ -
- {props.children} -
+
+ {props.children} +
- -
+ +
+ ) } diff --git a/src/hooks/data/use-note.ts b/src/hooks/data/use-note.ts index f131345b9c..2888038393 100644 --- a/src/hooks/data/use-note.ts +++ b/src/hooks/data/use-note.ts @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query' -import { useParams } from 'next/navigation' +import { useNoteId } from '~/providers/note/note-id-provider' import { queries } from '~/queries/definition' export const useNoteData = () => { @@ -18,7 +18,7 @@ export const useNoteData = () => { } export const useNoteNId = () => { - return (useParams() as { id?: string }).id + return useNoteId() } export const useNoteByNidQuery = (nid: string) => { diff --git a/src/providers/note/note-id-provider.tsx b/src/providers/note/note-id-provider.tsx new file mode 100644 index 0000000000..b187605f48 --- /dev/null +++ b/src/providers/note/note-id-provider.tsx @@ -0,0 +1,7 @@ +'use client' + +import { createContextState } from 'foxact/context-state' + +export const [NoteIdProvider, useNoteId, useSetNoteId] = createContextState< + undefined | string +>(undefined)