[Lighbox perf - 1] Fix memoization of List component, defer re-rendering when opening lightbox (#9759)
* memoize FlatList_INTERNAL * defer render, put handleScrolledDownChange in non reactive callback * lintfix useDedupe
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react'
|
import {useCallback, useRef} from 'react'
|
||||||
|
|
||||||
export const useDedupe = (timeout = 250) => {
|
export function useDedupe(timeout = 250) {
|
||||||
const canDo = React.useRef(true)
|
const canDo = useRef(true)
|
||||||
|
|
||||||
return React.useCallback(
|
return useCallback(
|
||||||
(cb: () => unknown) => {
|
(cb: () => unknown) => {
|
||||||
if (canDo.current) {
|
if (canDo.current) {
|
||||||
canDo.current = false
|
canDo.current = false
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {memo} from 'react'
|
import {forwardRef, memo, useDeferredValue, useMemo} from 'react'
|
||||||
import {RefreshControl, type ViewToken} from 'react-native'
|
import {RefreshControl, type ViewToken} from 'react-native'
|
||||||
import {
|
import {
|
||||||
type FlatListPropsWithLayout,
|
type FlatListPropsWithLayout,
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
import {updateActiveVideoViewAsync} from '@haileyok/bluesky-video'
|
import {updateActiveVideoViewAsync} from '@haileyok/bluesky-video'
|
||||||
|
|
||||||
import {useDedupe} from '#/lib/hooks/useDedupe'
|
import {useDedupe} from '#/lib/hooks/useDedupe'
|
||||||
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {useScrollHandlers} from '#/lib/ScrollContext'
|
import {useScrollHandlers} from '#/lib/ScrollContext'
|
||||||
import {addStyle} from '#/lib/styles'
|
import {addStyle} from '#/lib/styles'
|
||||||
import {useLightbox} from '#/state/lightbox'
|
import {useLightbox} from '#/state/lightbox'
|
||||||
@@ -43,7 +44,7 @@ export type ListRef = React.RefObject<FlatList_INTERNAL | null>
|
|||||||
|
|
||||||
const SCROLLED_DOWN_LIMIT = 200
|
const SCROLLED_DOWN_LIMIT = 200
|
||||||
|
|
||||||
let List = React.forwardRef<ListMethods, ListProps>(
|
let List = forwardRef<ListMethods, ListProps>(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
onScrolledDownChange,
|
onScrolledDownChange,
|
||||||
@@ -63,9 +64,11 @@ let List = React.forwardRef<ListMethods, ListProps>(
|
|||||||
const dedupe = useDedupe(400)
|
const dedupe = useDedupe(400)
|
||||||
const scrollsToTop = useAllowScrollToTop()
|
const scrollsToTop = useAllowScrollToTop()
|
||||||
|
|
||||||
function handleScrolledDownChange(didScrollDown: boolean) {
|
const handleScrolledDownChange = useNonReactiveCallback(
|
||||||
onScrolledDownChange?.(didScrollDown)
|
(didScrollDown: boolean) => {
|
||||||
}
|
onScrolledDownChange?.(didScrollDown)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// Intentionally destructured outside the main thread closure.
|
// Intentionally destructured outside the main thread closure.
|
||||||
// See https://github.com/bluesky-social/social-app/pull/4108.
|
// See https://github.com/bluesky-social/social-app/pull/4108.
|
||||||
@@ -106,7 +109,7 @@ let List = React.forwardRef<ListMethods, ListProps>(
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const [onViewableItemsChanged, viewabilityConfig] = React.useMemo(() => {
|
const [onViewableItemsChanged, viewabilityConfig] = useMemo(() => {
|
||||||
if (!onItemSeen) {
|
if (!onItemSeen) {
|
||||||
return [undefined, undefined]
|
return [undefined, undefined]
|
||||||
}
|
}
|
||||||
@@ -187,5 +190,5 @@ export {List}
|
|||||||
const useAllowScrollToTop = IS_IOS ? useAllowScrollToTopIOS : () => undefined
|
const useAllowScrollToTop = IS_IOS ? useAllowScrollToTopIOS : () => undefined
|
||||||
function useAllowScrollToTopIOS() {
|
function useAllowScrollToTopIOS() {
|
||||||
const {activeLightbox} = useLightbox()
|
const {activeLightbox} = useLightbox()
|
||||||
return !activeLightbox
|
return useDeferredValue(!activeLightbox)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {forwardRef} from 'react'
|
import {forwardRef, memo} from 'react'
|
||||||
import {type FlatListComponent} from 'react-native'
|
import {type FlatListComponent, View, type ViewProps} from 'react-native'
|
||||||
import {View, type ViewProps} from 'react-native'
|
|
||||||
import Animated from 'react-native-reanimated'
|
import Animated from 'react-native-reanimated'
|
||||||
import {type FlatListPropsWithLayout} from 'react-native-reanimated'
|
import {type FlatListPropsWithLayout} from 'react-native-reanimated'
|
||||||
|
|
||||||
@@ -10,7 +9,7 @@ import {type FlatListPropsWithLayout} from 'react-native-reanimated'
|
|||||||
* Avoid using `FlatList_INTERNAL` and use `List` where possible.
|
* Avoid using `FlatList_INTERNAL` and use `List` where possible.
|
||||||
* The types are a bit wrong on `FlatList_INTERNAL`
|
* The types are a bit wrong on `FlatList_INTERNAL`
|
||||||
*/
|
*/
|
||||||
export const FlatList_INTERNAL = Animated.FlatList
|
export const FlatList_INTERNAL = memo(Animated.FlatList)
|
||||||
export type FlatList_INTERNAL<ItemT = any> = Omit<
|
export type FlatList_INTERNAL<ItemT = any> = Omit<
|
||||||
FlatListComponent<ItemT, FlatListPropsWithLayout<ItemT>>,
|
FlatListComponent<ItemT, FlatListPropsWithLayout<ItemT>>,
|
||||||
'CellRendererComponent'
|
'CellRendererComponent'
|
||||||
|
|||||||
Reference in New Issue
Block a user