Skip to content

Commit

Permalink
perf: improve toc perfermance
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <tukon479@gmail.com>
  • Loading branch information
Innei committed Aug 12, 2022
1 parent 7c06479 commit 4629415
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 24 deletions.
6 changes: 4 additions & 2 deletions src/components/universal/Markdown/renderers/image.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { sanitizeUrl } from 'markdown-to-jsx'
import { reaction } from 'mobx'
import { observer } from 'mobx-react-lite'
import type { FC } from 'react'
Expand Down Expand Up @@ -107,10 +108,11 @@ export const MImage: FC<
>
> = (props) => {
const { src, alt } = props
const sanitizedUrl = sanitizeUrl(src!)
const isClient = useIsClient()
return !isClient ? (
<img src={src} alt={alt} />
<img src={sanitizedUrl!} alt={alt} />
) : (
<_Image src={src!} alt={alt} />
<_Image src={sanitizedUrl!} alt={alt} />
)
}
92 changes: 70 additions & 22 deletions src/components/widgets/Toc/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import type { FC } from 'react'
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { TransitionGroup } from 'react-transition-group'

import { RightLeftTransitionView } from '~/components/universal/Transition/right-left'
import { CustomEventTypes } from '~/types/events'
import { eventBus } from '~/utils/event-emitter'

import { RightLeftTransitionView } from '../../universal/Transition/right-left'
import styles from './index.module.css'
import { TocItem } from './item'

Expand All @@ -17,10 +17,15 @@ export type TocProps = {
useAsWeight?: boolean
}

type Headings = {
depth: number
index: number
title: string
}[]
export const Toc: FC<TocProps> = memo(
({ headings: $headings, useAsWeight }) => {
const containerRef = useRef<HTMLDivElement>(null)
const headings = useMemo(() => {
const headings: Headings = useMemo(() => {
return Array.from($headings).map((el) => {
const depth = +el.tagName.slice(1)
const title = el.id || el.textContent || ''
Expand Down Expand Up @@ -69,6 +74,17 @@ export const Toc: FC<TocProps> = memo(
}, 350)
}, [])

const rootDepth = useMemo(
() =>
headings?.length
? (headings.reduce(
(d: number, cur) => Math.min(d, cur.depth),
headings[0]?.depth || 0,
) as any as number)
: 0,
[headings],
)

return (
<section
className={classNames(
Expand All @@ -83,27 +99,15 @@ export const Toc: FC<TocProps> = memo(
>
<TransitionGroup className={styles['anime-wrapper']}>
{headings &&
headings.map((heading, i) => {
headings.map((heading) => {
return (
<RightLeftTransitionView
timeout={{ enter: 100 * i }}
key={`${heading.index}${heading.title}`}
>
<TocItem
index={heading.index}
onClick={handleItemClick}
active={heading.index === index}
depth={heading.depth}
title={heading.title}
key={heading.title}
rootDepth={
headings.reduce(
(d: number, cur) => Math.min(d, cur.depth),
headings[0].depth,
) as any as number
}
/>
</RightLeftTransitionView>
<MemoedItem
heading={heading}
isActive={heading.index === index}
onClick={handleItemClick}
key={heading.title}
rootDepth={rootDepth}
/>
)
})}
</TransitionGroup>
Expand All @@ -112,3 +116,47 @@ export const Toc: FC<TocProps> = memo(
)
},
)
const MemoedItem = memo<{
isActive: boolean
heading: Headings[0]
rootDepth: number
onClick: (i: number) => void
}>(
(props) => {
const { heading, isActive, onClick, rootDepth } = props

return (
<RightLeftTransitionView
timeout={
useRef({
exit: 50,
enter: 50 * heading.index,
}).current
}
key={heading.title}
>
<TocItem
index={heading.index}
onClick={onClick}
active={isActive}
depth={heading.depth}
title={heading.title}
key={heading.title}
rootDepth={rootDepth}
/>
</RightLeftTransitionView>
)
},
(a, b) => {
// FUCK react transition group alway inject onExited props into Child element, but this props alway change, so ignore it.

return (
a.heading === b.heading &&
a.isActive === b.isActive &&
a.onClick === b.onClick &&
a.rootDepth === b.rootDepth
)
},
)

MemoedItem.displayName = 'MemoedItem'

0 comments on commit 4629415

Please sign in to comment.