Skip to content

Commit 62e86ac

Browse files
committed
refactor: optimize CardHeader and CardSettings components for improved performance and readability
1 parent 1104191 commit 62e86ac

2 files changed

Lines changed: 40 additions & 31 deletions

File tree

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { memo, useMemo } from 'react'
12
import { MY_LANGUAGES_OPTION } from '../config'
23

34
type HeaderTitleProps = {
@@ -12,27 +13,23 @@ type HeaderTitleProps = {
1213
}
1314
children?: React.ReactNode
1415
}
15-
export const CardHeader = ({ label, fallbackTag, selectedTag, children }: HeaderTitleProps) => {
16+
const CardHeader = ({ label, fallbackTag, selectedTag, children }: HeaderTitleProps) => {
1617
if (children) {
1718
return <>{children}</>
1819
}
1920

20-
if (!selectedTag || selectedTag.value === fallbackTag.value) {
21-
return <>{label}</>
22-
}
23-
24-
if (selectedTag.value === MY_LANGUAGES_OPTION.value) {
25-
return (
26-
<>
27-
{label} <span className="blockHeaderHighlight">{MY_LANGUAGES_OPTION.label}</span>
28-
</>
29-
)
30-
}
21+
const highlightLabel = useMemo(() => {
22+
if (!selectedTag || selectedTag.value === fallbackTag.value) return null
23+
if (selectedTag.value === MY_LANGUAGES_OPTION.value) return MY_LANGUAGES_OPTION.label
24+
return selectedTag.label
25+
}, [selectedTag, fallbackTag])
3126

3227
return (
3328
<>
3429
{label}
35-
<span className="blockHeaderHighlight">{selectedTag.label}</span>
30+
{highlightLabel && <span className="blockHeaderHighlight">{highlightLabel}</span>}
3631
</>
3732
)
3833
}
34+
35+
export const MemoizedCardHeader = memo(CardHeader)

src/features/cards/components/CardSettings.tsx

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { Menu, MenuDivider, MenuItem, SubMenu } from '@szhsin/react-menu'
2-
import { useCallback, useMemo } from 'react'
2+
import { memo, useCallback, useMemo } from 'react'
33
import { AiOutlineCode } from 'react-icons/ai'
44
import { BsBoxArrowInUpRight } from 'react-icons/bs'
5+
import { FiFilter } from 'react-icons/fi'
56
import { GoGear } from 'react-icons/go'
67
import { IoTrashBinOutline } from 'react-icons/io5'
78
import { LiaSortSolid } from 'react-icons/lia'
89
import { MdDateRange } from 'react-icons/md'
10+
import { useMediaQuery } from 'react-responsive'
911
import { ref } from 'src/config'
1012
import { useUserPreferences } from 'src/stores/preferences'
13+
import { useShallow } from 'zustand/shallow'
1114
import { MY_LANGUAGES_OPTION } from '../config'
1215

1316
type SortOption = { label: string; value: string; icon?: React.ReactNode }
@@ -27,7 +30,7 @@ type CardSettingsProps = {
2730
const DEFAULT_SORT_OPTIONS = [{ label: 'Newest', value: 'published_at', icon: <MdDateRange /> }]
2831
const SPECIAL_LABELS = ['global', MY_LANGUAGES_OPTION.label.toLowerCase()]
2932

30-
export const CardSettings = ({
33+
const CardSettings = ({
3134
id,
3235
url,
3336
sortBy,
@@ -38,30 +41,34 @@ export const CardSettings = ({
3841
customStartMenuItems,
3942
sortOptions,
4043
}: CardSettingsProps) => {
41-
const userSelectedTags = useUserPreferences((state) => state.userSelectedTags)
42-
const openLinksNewTab = useUserPreferences((state) => state.openLinksNewTab)
43-
const removeCard = useUserPreferences((state) => state.removeCard)
44-
const setCardSettings = useUserPreferences((state) => state.setCardSettings)
45-
const cardSettings = useUserPreferences((state) => state.cardsSettings[id])
44+
const { userSelectedTags, openLinksNewTab, removeCard, setCardSettings, cardSettings } =
45+
useUserPreferences(
46+
useShallow((state) => ({
47+
userSelectedTags: state.userSelectedTags,
48+
openLinksNewTab: state.openLinksNewTab,
49+
removeCard: state.removeCard,
50+
setCardSettings: state.setCardSettings,
51+
cardSettings: state.cardsSettings?.[id],
52+
}))
53+
)
4654

4755
const userTagsMemo = useMemo(() => {
48-
const newTags = userSelectedTags.sort((a, b) => a.label.localeCompare(b.label))
49-
let tags = [...newTags]
50-
if (globalTag) {
51-
tags = [...tags, globalTag]
52-
}
53-
54-
tags = [...tags, MY_LANGUAGES_OPTION]
56+
const tags = [...userSelectedTags]
57+
.sort((a, b) => a.label.localeCompare(b.label))
58+
.concat(globalTag ? [globalTag] : [])
59+
.concat(MY_LANGUAGES_OPTION)
5560
return tags
5661
}, [userSelectedTags, globalTag])
5762

58-
const resolvedSortOptions =
59-
typeof sortOptions === 'function'
63+
const resolvedSortOptions = useMemo(() => {
64+
return typeof sortOptions === 'function'
6065
? sortOptions(DEFAULT_SORT_OPTIONS)
6166
: sortOptions || DEFAULT_SORT_OPTIONS
67+
}, [sortOptions])
6268

6369
const onOpenSourceUrlClicked = useCallback(() => {
64-
let link = `${url}?${ref}`
70+
if (!url) return
71+
const link = `${url}?${ref}`
6572
window.open(link, openLinksNewTab ? '_blank' : '_self')
6673
}, [url, openLinksNewTab])
6774

@@ -70,9 +77,12 @@ export const CardSettings = ({
7077
[userTagsMemo]
7178
)
7279

80+
const isMobile = useMediaQuery({ maxWidth: 767 })
81+
const menuIcon = isMobile ? <FiFilter /> : <GoGear />
82+
7383
return (
7484
<Menu
75-
menuButton={<GoGear />}
85+
menuButton={menuIcon}
7686
theming="dark"
7787
portal={true}
7888
className={`menuItem`}
@@ -144,3 +154,5 @@ export const CardSettings = ({
144154
</Menu>
145155
)
146156
}
157+
158+
export const MemoizedCardSettings = memo(CardSettings)

0 commit comments

Comments
 (0)