feat: 使用 useIsFocused hook 优化组件渲染,页面失焦时不渲染列表项以减少内存占用
This commit is contained in:
parent
912c380a8a
commit
ef4114f694
|
|
@ -1,4 +1,5 @@
|
|||
import { FontAwesome, Fontisto, Ionicons } from '@expo/vector-icons'
|
||||
import { useIsFocused } from '@react-navigation/native'
|
||||
import { FlashList } from '@shopify/flash-list'
|
||||
import { useFocusEffect, useRouter } from 'expo-router'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
|
@ -42,8 +43,11 @@ const Generate = observer(function Generate() {
|
|||
const templates = useTemplates()
|
||||
const { runTemplate } = useTemplateActions()
|
||||
|
||||
// 直接使用 useIsFocused hook,页面失焦时不渲染列表项以减少内存占用
|
||||
const isFocused = useIsFocused()
|
||||
|
||||
useFocusEffect(() => {
|
||||
if (!isAuthenticated) {
|
||||
if (!isAuthenticated && isFocused) {
|
||||
router.replace('/')
|
||||
router.push('/auth')
|
||||
}
|
||||
|
|
@ -253,11 +257,13 @@ const Generate = observer(function Generate() {
|
|||
item={item}
|
||||
key={item?.id}
|
||||
itemWidth={itemWidth}
|
||||
// 页面失焦时不渲染,减少内存占用
|
||||
isVisible={isFocused}
|
||||
onSelect={() => handleSelectTemplate(item)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
[selectedTemplateId, itemWidth, handleSelectTemplate],
|
||||
[selectedTemplateId, itemWidth, handleSelectTemplate, isFocused],
|
||||
)
|
||||
|
||||
const ListHeader = useMemo(() => {
|
||||
|
|
@ -457,9 +463,16 @@ type TemplateItemProps = {
|
|||
item: Template
|
||||
itemWidth: number
|
||||
isSelected: boolean
|
||||
isVisible?: boolean
|
||||
onSelect: () => void
|
||||
}
|
||||
const TemplateItem = memo<TemplateItemProps>(function TemplateItem({ item, itemWidth, isSelected, onSelect }) {
|
||||
const TemplateItem = memo<TemplateItemProps>(function TemplateItem({
|
||||
item,
|
||||
itemWidth,
|
||||
isSelected,
|
||||
isVisible = true,
|
||||
onSelect,
|
||||
}) {
|
||||
return (
|
||||
<Block
|
||||
key={item?.id}
|
||||
|
|
@ -475,7 +488,7 @@ const TemplateItem = memo<TemplateItemProps>(function TemplateItem({ item, itemW
|
|||
onClick={onSelect}
|
||||
>
|
||||
{/* <Img className="size-full" contentFit="cover" src={item.image} /> */}
|
||||
<VideoBox style={{ width: itemWidth, height: itemWidth }} url={item.videoUrl} />
|
||||
{isVisible && <VideoBox style={{ width: itemWidth, height: itemWidth }} url={item.videoUrl} />}
|
||||
|
||||
{isSelected && <Block className="absolute inset-0 bg-black/60" />}
|
||||
{isSelected && <Block className="absolute inset-[-5px] border-[3px] border-accent" />}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Ionicons } from '@expo/vector-icons'
|
||||
import { useIsFocused } from '@react-navigation/native'
|
||||
import { Block, ConfirmModal, Img, ListEmpty, Text, Toast, VideoBox } from '@share/components'
|
||||
import { FlashList } from '@shopify/flash-list'
|
||||
import { LinearGradient } from 'expo-linear-gradient'
|
||||
|
|
@ -54,6 +55,9 @@ const Index = observer(function Index() {
|
|||
const [allItems, setAllItems] = useState<MediaItem[]>([])
|
||||
const [selectedItem, setSelectedItem] = useState<MediaItem | null>(null)
|
||||
|
||||
// 直接使用 useIsFocused hook,无需手动管理状态
|
||||
const isFocused = useIsFocused()
|
||||
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
const [loadingMore, setLoadingMore] = useState(false)
|
||||
const [hasMore, setHasMore] = useState(true)
|
||||
|
|
@ -391,11 +395,12 @@ const Index = observer(function Index() {
|
|||
isSelected={selectedId === item.id}
|
||||
item={item}
|
||||
itemWidth={ITEM_WIDTH}
|
||||
isVisible={index < 9 || visibleIdsRef.current.has(item.id)}
|
||||
// 页面失焦时不渲染,减少内存占用
|
||||
isVisible={isFocused && (index < 9 || visibleIdsRef.current.has(item.id))}
|
||||
onSelect={() => setSelectedItem(item)}
|
||||
/>
|
||||
),
|
||||
[selectedId],
|
||||
[selectedId, isFocused],
|
||||
)
|
||||
|
||||
const keyExtractor = useCallback((item: MediaItem) => item.id, [])
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { AntDesign, EvilIcons, FontAwesome, Ionicons, MaterialCommunityIcons } from '@expo/vector-icons'
|
||||
import { useIsFocused } from '@react-navigation/native'
|
||||
import { Block, ConfirmModal, Img, Input, ListEmpty, Text, Toast, VideoBox } from '@share/components'
|
||||
import { FlashList } from '@shopify/flash-list'
|
||||
import * as ImagePicker from 'expo-image-picker'
|
||||
|
|
@ -47,6 +48,9 @@ const Sync = observer(() => {
|
|||
const [isSelectionMode, setIsSelectionMode] = useState(false)
|
||||
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())
|
||||
|
||||
// 直接使用 useIsFocused hook,页面失焦时不渲染列表项以减少内存占用
|
||||
const isFocused = useIsFocused()
|
||||
|
||||
const { connectedDevice, isScanning, transferProgress } = bleStore.state
|
||||
|
||||
const itemWidth = Math.floor((screenWidth - 12 * 2 - 12 * 2) / 3)
|
||||
|
|
@ -380,16 +384,18 @@ const Sync = observer(() => {
|
|||
isSelectionMode={isSelectionMode}
|
||||
itemWidth={itemWidth}
|
||||
post={post}
|
||||
// 页面失焦时不渲染,减少内存占用
|
||||
isVisible={isFocused}
|
||||
onSelect={handleItemSelect}
|
||||
key={post?.id}
|
||||
/>
|
||||
)
|
||||
},
|
||||
[isSelectionMode, selectedIds, selectedItem, itemWidth, handleItemSelect],
|
||||
[isSelectionMode, selectedIds, selectedItem, itemWidth, handleItemSelect, isFocused],
|
||||
)
|
||||
|
||||
return (
|
||||
<Block className="relative flex-1">
|
||||
<Block className="relative flex-1 bg-black">
|
||||
<BannerSection />
|
||||
|
||||
<Block className="z-10 flex-1">
|
||||
|
|
@ -658,12 +664,14 @@ const GridItem = memo(
|
|||
isSelected,
|
||||
isSelectionMode,
|
||||
itemWidth,
|
||||
isVisible = true,
|
||||
onSelect,
|
||||
}: {
|
||||
post: any
|
||||
isSelected: boolean
|
||||
isSelectionMode: boolean
|
||||
itemWidth: number
|
||||
isVisible?: boolean
|
||||
onSelect: (post: any) => void
|
||||
}) => {
|
||||
// 渲染状态标记
|
||||
|
|
@ -707,7 +715,7 @@ const GridItem = memo(
|
|||
style={{ transform: [{ skewX: '-6deg' }], height: itemWidth, width: itemWidth }}
|
||||
>
|
||||
<Block style={{ height: itemWidth, width: itemWidth }}>
|
||||
<Img className="size-full" src={post.imageUrl} />
|
||||
{isVisible && <Img className="size-full" src={post.imageUrl} />}
|
||||
</Block>
|
||||
{isSelected && <Block className="absolute inset-0 border-[3px] border-accent" />}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { useIsFocused } from '@react-navigation/native'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
import Svg, { Circle, Defs, Pattern, Rect } from 'react-native-svg'
|
||||
|
||||
|
|
@ -19,6 +20,9 @@ const BannerSection = memo<BannerProps>(function Banner({ bgVideo }) {
|
|||
setBgurl(bgVideo)
|
||||
}, [bgVideo])
|
||||
|
||||
const isFocused = useIsFocused()
|
||||
if (!isFocused) return null
|
||||
|
||||
return (
|
||||
<Block className="absolute inset-0 z-0 overflow-hidden">
|
||||
{/* 使用较小的分辨率降低内存占用 */}
|
||||
|
|
|
|||
Loading…
Reference in New Issue