Skip to content

Commit

Permalink
perf: reduce re-render when ctx menu open
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <i@innei.in>
  • Loading branch information
Innei committed Sep 12, 2024
1 parent 85d8e22 commit 96ff9f6
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 31 deletions.
2 changes: 2 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export default defineConfig(
"unicorn/prefer-math-trunc": "off",
"@eslint-react/no-clone-element": 0,
"@eslint-react/hooks-extra/no-direct-set-state-in-use-effect": 0,
// NOTE: Disable this temporarily
"react-compiler/react-compiler": 0,
"no-restricted-syntax": 0,
"no-restricted-globals": [
"error",
Expand Down
3 changes: 3 additions & 0 deletions src/renderer/src/components/common/ShadowDOM.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useUISettingKey } from "@renderer/atoms/settings/ui"
import { useReduceMotion } from "@renderer/hooks/biz/useReduceMotion"
import { useIsDark } from "@renderer/hooks/common"
import { nanoid } from "nanoid"
import type { FC, PropsWithChildren, ReactNode } from "react"
Expand Down Expand Up @@ -100,6 +101,7 @@ export const ShadowDOM: FC<PropsWithChildren<React.HTMLProps<HTMLElement>>> & {
const dark = useIsDark()

const uiFont = useUISettingKey("uiFontFamily")
const reduceMotion = useReduceMotion()

return (
<root.div {...rest}>
Expand All @@ -112,6 +114,7 @@ export const ShadowDOM: FC<PropsWithChildren<React.HTMLProps<HTMLElement>>> & {
[uiFont],
)}
id="shadow-html"
data-motion-reduce={reduceMotion}
data-theme={dark ? "dark" : "light"}
className="font-theme"
>
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/src/components/ui/markdown/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { parseHtml } from "@renderer/lib/parse-html"
import type { RemarkOptions } from "@renderer/lib/parse-markdown"
import { parseMarkdown } from "@renderer/lib/parse-markdown"
import { cn } from "@renderer/lib/utils"
import { createElement, Fragment, useEffect, useMemo, useState } from "react"
import { createElement, Fragment, memo, useEffect, useMemo, useState } from "react"

import { MarkdownRenderContainerRefContext } from "./context"

Expand Down Expand Up @@ -34,7 +34,7 @@ export const Markdown: Component<
)
}

export const HTML = <A extends keyof JSX.IntrinsicElements = "div">(
const HTMLImpl = <A extends keyof JSX.IntrinsicElements = "div">(
props: {
children: string | null | undefined
as: A
Expand Down Expand Up @@ -83,3 +83,5 @@ export const HTML = <A extends keyof JSX.IntrinsicElements = "div">(
</MarkdownRenderContainerRefContext.Provider>
)
}

export const HTML = memo(HTMLImpl)
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { FeedViewType } from "@renderer/lib/enum"
import { useEntryContentContext } from "@renderer/modules/entry-content/hooks"
import { useEntryContentContextSelector } from "@renderer/modules/entry-content/hooks"
import * as React from "react"

import { ensureAndRenderTimeStamp } from "../utils"

export const MarkdownP: Component<
React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
> = ({ children, ...props }) => {
const { view } = useEntryContentContext()
const view = useEntryContentContextSelector((s) => s.view)
const parseTimeline = view === FeedViewType.Audios
if (parseTimeline && typeof children === "string") {
const renderer = ensureAndRenderTimeStamp(children)
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/src/modules/entry-content/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import { useEntry } from "@renderer/store/entry/hooks"
import { useFeedById } from "@renderer/store/feed"
import { noop } from "foxact/noop"
import { AnimatePresence, m } from "framer-motion"
import { useMemo, useState } from "react"
import { memo, useMemo, useState } from "react"

import { useEntryContentScrollToTop, useEntryTitleMeta } from "./atoms"
import { EntryReadHistory } from "./components/EntryReadHistory"

export function EntryHeader({
function EntryHeaderImpl({
view,
entryId,
className,
Expand Down Expand Up @@ -211,3 +211,5 @@ const ElectronAdditionActions = window.electron
)
}
: noop

export const EntryHeader = memo(EntryHeaderImpl)
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isDev } from "@renderer/constants"
import { useContext } from "react"
import { useContext, useContextSelector } from "use-context-selector"

import { EntryContentContext } from "./provider"

Expand All @@ -10,3 +10,6 @@ export const useEntryContentContext = () => {
}
return ctx
}

export const useEntryContentContextSelector = <T>(selector: (ctx: EntryContentContext) => T) =>
useContextSelector(EntryContentContext, selector)
37 changes: 19 additions & 18 deletions src/renderer/src/modules/entry-content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { getPreferredTitle, useFeedById, useFeedHeaderTitle } from "@renderer/st
import type { FallbackRender } from "@sentry/react"
import { ErrorBoundary } from "@sentry/react"
import type { FC } from "react"
import { useEffect, useLayoutEffect, useRef } from "react"
import { memo, useEffect, useLayoutEffect, useMemo, useRef } from "react"
import { useHotkeys } from "react-hotkeys-hook"

import { LoadingWithIcon } from "../../components/ui/loading"
Expand Down Expand Up @@ -137,6 +137,19 @@ export const EntryContentRender: Component<{ entryId: string }> = ({ entryId, cl

const isPeekModal = useInPeekModal()

const contentAccessories = useMemo(
() => (isPeekModal ? undefined : <ContainerToc key={entryId} />),
[entryId, isPeekModal],
)
const stableRenderStyle = useMemo(
() =>
readerFontFamily
? {
fontFamily: readerFontFamily,
}
: undefined,
[readerFontFamily],
)
if (!entry) return null

const content = entry?.entries.content ?? data?.entries.content
Expand All @@ -162,13 +175,7 @@ export const EntryContentRender: Component<{ entryId: string }> = ({ entryId, cl
ref={scrollerRef}
>
<div
style={
readerFontFamily
? {
fontFamily: readerFontFamily,
}
: undefined
}
style={stableRenderStyle}
className="duration-200 ease-in-out animate-in fade-in slide-in-from-bottom-24 f-motion-reduce:fade-in-0 f-motion-reduce:slide-in-from-bottom-0"
key={entry.entries.id}
>
Expand Down Expand Up @@ -222,16 +229,10 @@ export const EntryContentRender: Component<{ entryId: string }> = ({ entryId, cl
{!isInReadabilityMode ? (
<ShadowDOM>
<HTML
accessory={isPeekModal ? undefined : <ContainerToc key={entryId} />}
accessory={contentAccessories}
as="article"
className="prose !max-w-full dark:prose-invert prose-h1:text-[1.6em]"
style={
readerFontFamily
? {
fontFamily: readerFontFamily,
}
: undefined
}
style={stableRenderStyle}
renderInlineStyle={readerRenderInlineStyle}
>
{content}
Expand Down Expand Up @@ -414,7 +415,7 @@ const RenderError: FallbackRender = ({ error }) => {
)
}

const ContainerToc: FC = () => {
const ContainerToc: FC = memo(() => {
const wrappedElement = useWrappedElement()
return (
<RootPortal to={wrappedElement!}>
Expand All @@ -433,4 +434,4 @@ const ContainerToc: FC = () => {
</div>
</RootPortal>
)
}
})
2 changes: 1 addition & 1 deletion src/renderer/src/modules/entry-content/provider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FeedViewType } from "@renderer/lib/enum"
import { createContext } from "react"
import { createContext } from "use-context-selector"

export interface EntryContentContext {
entryId: string
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/src/modules/feed-column/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { stopPropagation } from "@renderer/lib/dom"
import { cn } from "@renderer/lib/utils"
import { m } from "framer-motion"
import type { FC, PropsWithChildren } from "react"
import { useCallback, useRef, useState } from "react"
import { memo, useCallback, useRef, useState } from "react"
import { Link } from "react-router-dom"
import { toast } from "sonner"

Expand All @@ -29,7 +29,7 @@ const useBackHome = (active: number) => {
)
}

export const FeedColumnHeader = () => {
export const FeedColumnHeader = memo(() => {
const [active] = useSidebarActiveView()

const navigateBackHome = useBackHome(active)
Expand Down Expand Up @@ -70,7 +70,7 @@ export const FeedColumnHeader = () => {
</div>
</div>
)
}
})

const LayoutActionButton = () => {
const feedColumnShow = useFeedColumnShow()
Expand Down
7 changes: 5 additions & 2 deletions src/renderer/src/modules/feed-column/list.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import * as HoverCard from "@radix-ui/react-hover-card"
import { useUISettingKey } from "@renderer/atoms/settings/ui"
import { ScrollArea } from "@renderer/components/ui/scroll-area"
Expand All @@ -14,7 +15,7 @@ import { useFeedStore } from "@renderer/store/feed"
import { getSubscriptionByFeedId, useSubscriptionByView } from "@renderer/store/subscription"
import { useFeedUnreadStore } from "@renderer/store/unread"
import { AnimatePresence, m } from "framer-motion"
import { Fragment, useMemo, useState } from "react"
import { Fragment, memo, useMemo, useState } from "react"
import { Link } from "react-router-dom"

import {
Expand Down Expand Up @@ -57,7 +58,7 @@ const useUpdateUnreadCount = () => {
})
}

export function FeedList({ className, view }: { className?: string; view: number }) {
function FeedListImpl({ className, view }: { className?: string; view: number }) {
const [expansion, setExpansion] = useState(false)
const data = useGroupedData(view)

Expand Down Expand Up @@ -348,3 +349,5 @@ const SortableList = (props: FeedListProps) => {
}
}
}

export const FeedList = memo(FeedListImpl)

0 comments on commit 96ff9f6

Please sign in to comment.