Skip to content

Commit

Permalink
Avoid re-rendering from useIsFocused
Browse files Browse the repository at this point in the history
  • Loading branch information
samholmes committed Jan 14, 2025
1 parent 4f9b4b3 commit 01fe3b9
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 19 deletions.
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,7 @@ SPEC CHECKSUMS:
CNIOLinux: 62e3505f50de558c393dc2f273dde71dcce518da
CNIOWindows: 3047f2d8165848a3936a0a755fee27c6b5ee479b
disklet: e7ed3e673ccad9d175a1675f9f3589ffbf69a5fd
DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
edge-core-js: e824579a514ac6bbe61b3d89541efb9019569057
edge-currency-accountbased: 297022eeeba7781f521c93bbba54b8288ba25ddc
edge-currency-plugins: 797acb6852c2f0a3ccf5e6bde510cc85ee591402
Expand All @@ -1101,7 +1101,7 @@ SPEC CHECKSUMS:
FirebaseInstallations: 766dabca09fd94aef922538aaf144cc4a6fb6869
FirebaseMessaging: 585984d0a1df120617eb10b44cad8968b859815e
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
gRPC-Swift: 74adcaaa62ac5e0a018938840328cb1fdfb09e7b
Expand Down
50 changes: 33 additions & 17 deletions src/state/SceneScrollState.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useIsFocused } from '@react-navigation/native'
import { useMemo } from 'react'
import { useFocusEffect } from '@react-navigation/native'
import { useCallback, useMemo } from 'react'
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native'
import { SharedValue, useAnimatedReaction, useAnimatedScrollHandler, useSharedValue, useWorkletCallback } from 'react-native-reanimated'
import { SharedValue, useAnimatedReaction, useAnimatedScrollHandler, useSharedValue, useWorkletCallback, withTiming } from 'react-native-reanimated'

import { createStateProvider } from './createStateProvider'

Expand Down Expand Up @@ -51,20 +51,28 @@ export const useSceneScrollHandler = (): SceneScrollHandler => {
const scrollMomentumEndEvent = useSceneScrollContext(state => state.scrollMomentumEndEvent)
const scrollY = useSceneScrollContext(state => state.scrollY)

const isFocused = useSharedValue(false)
useFocusEffect(
useCallback(() => {
isFocused.value = true
return () => {
isFocused.value = false
}
}, [isFocused])
)

// This fixes a bug during scene transition where the scene that is being
// left was the last to update the scrollY value.
const isFocused = useIsFocused()
const localScrollY = useSharedValue(0)
useAnimatedReaction(
() => {
return isFocused
return isFocused.value
},
isFocused => {
if (isFocused && localScrollY.value !== scrollY.value) {
scrollY.value = localScrollY.value
scrollY.value = withTiming(localScrollY.value, { duration: 300 })
}
},
[isFocused]
}
)

// In each handler, we check `isFocused` to avoid mutating state if the
Expand All @@ -73,39 +81,39 @@ export const useSceneScrollHandler = (): SceneScrollHandler => {
onScroll: (nativeEvent: NativeScrollEvent) => {
'worklet'
// Avoids unexpected triggers
if (!isFocused) return
if (!isFocused.value) return

// Condition avoids thrashing
if (scrollY.value !== nativeEvent.contentOffset.y) {
localScrollY.value = nativeEvent.contentOffset.y
scrollY.value = localScrollY.value
scrollY.value = nativeEvent.contentOffset.y
}
},
onBeginDrag: (nativeEvent: NativeScrollEvent) => {
'worklet'
// Avoids unexpected triggers
if (!isFocused) return
if (!isFocused.value) return

scrollBeginEvent.value = nativeEvent
},
onEndDrag: nativeEvent => {
'worklet'
// Avoids unexpected triggers
if (!isFocused) return
if (!isFocused.value) return

scrollEndEvent.value = nativeEvent
},
onMomentumBegin: nativeEvent => {
'worklet'
// Avoids unexpected triggers
if (!isFocused) return
if (!isFocused.value) return

scrollMomentumBeginEvent.value = nativeEvent
},
onMomentumEnd: nativeEvent => {
'worklet'
// Avoids unexpected triggers
if (!isFocused) return
if (!isFocused.value) return

scrollMomentumEndEvent.value = nativeEvent
}
Expand All @@ -120,17 +128,25 @@ export const useSceneScrollWorkletHandler = () => {
const scrollY = useSceneScrollContext(state => state.scrollY)

// Create shared values for scroll position
const isFocused = useIsFocused()
const isFocused = useSharedValue(false)
useFocusEffect(
useCallback(() => {
isFocused.value = true
return () => {
isFocused.value = false
}
}, [isFocused])
)

const localScrollY = useSharedValue(0)

useAnimatedReaction(
() => {
return isFocused
return isFocused.value
},
isFocusedResult => {
if (isFocusedResult && localScrollY.value !== scrollY.value) {
scrollY.value = localScrollY.value
scrollY.value = withTiming(localScrollY.value, { duration: 300 })
}
}
)
Expand Down

0 comments on commit 01fe3b9

Please sign in to comment.