From 8c226d2f3e54c168c4e943ea20d2c3298eda480c Mon Sep 17 00:00:00 2001 From: Mo Gorhom Date: Sun, 15 Nov 2020 20:51:01 +0100 Subject: [PATCH 1/2] chore: added useReactiveVlaue/s --- src/components/bottomSheet/useTransition.ts | 10 +++-- src/hooks/index.ts | 2 + src/hooks/useReactiveValue.ts | 20 +++++++++ src/hooks/useReactiveValues.ts | 47 +++++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 src/hooks/useReactiveValue.ts create mode 100644 src/hooks/useReactiveValues.ts diff --git a/src/components/bottomSheet/useTransition.ts b/src/components/bottomSheet/useTransition.ts index 1d74cd669..3e980d05e 100644 --- a/src/components/bottomSheet/useTransition.ts +++ b/src/components/bottomSheet/useTransition.ts @@ -23,6 +23,7 @@ import { State } from 'react-native-gesture-handler'; import { useClock, useValue, snapPoint } from 'react-native-redash'; import type { BottomSheetAnimationConfigs } from './types'; import { GESTURE } from '../../constants'; +import { useReactiveValue, useReactiveValues } from '../../hooks'; interface TransitionProps extends Required { contentPanGestureState: Animated.Value; @@ -48,11 +49,12 @@ export const useTransition = ({ handlePanGestureTranslationY, handlePanGestureVelocityY, scrollableContentOffsetY, - snapPoints, + snapPoints: _snapPoints, initialPosition, }: TransitionProps) => { const currentGesture = useValue(GESTURE.UNDETERMINED); - const currentPosition = useValue(initialPosition); + const currentPosition = useReactiveValue(initialPosition); + const snapPoints = useReactiveValues(_snapPoints); const isPanningContent = useMemo( () => eq(contentPanGestureState, State.ACTIVE), @@ -86,11 +88,13 @@ export const useTransition = ({ frameTime: new Animated.Value(0), time: new Animated.Value(0), }), - [initialPosition] + // eslint-disable-next-line react-hooks/exhaustive-deps + [] ); const finishTiming = useMemo( () => [ + // debug('finish timing', config.toValue), set(currentGesture, GESTURE.UNDETERMINED), set(shouldAnimate, 0), set(currentPosition, config.toValue), diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 21fcfe49f..01316e143 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -2,3 +2,5 @@ export { useBottomSheetInternal } from './useBottomSheetInternal'; export { useScrollable } from './useScrollable'; export { useScrollableInternal } from './useScrollableInternal'; export { useStableCallback } from './useStableCallback'; +export { useReactiveValue } from './useReactiveValue'; +export { useReactiveValues } from './useReactiveValues'; diff --git a/src/hooks/useReactiveValue.ts b/src/hooks/useReactiveValue.ts new file mode 100644 index 000000000..bff84260b --- /dev/null +++ b/src/hooks/useReactiveValue.ts @@ -0,0 +1,20 @@ +import { useEffect, useRef } from 'react'; +import Animated from 'react-native-reanimated'; + +export const useReactiveValue = (value: number) => { + // ref + const ref = useRef>(null); + if (ref.current === null) { + // @ts-ignore + ref.current = new Animated.Value(value); + } + + // effects + useEffect(() => { + if (ref.current) { + ref.current.setValue(value); + } + }, [value]); + + return ref.current; +}; diff --git a/src/hooks/useReactiveValues.ts b/src/hooks/useReactiveValues.ts new file mode 100644 index 000000000..dc286951d --- /dev/null +++ b/src/hooks/useReactiveValues.ts @@ -0,0 +1,47 @@ +import { useEffect, useRef } from 'react'; +import Animated from 'react-native-reanimated'; + +export const useReactiveValues = (values: number[]) => { + // ref + const ref = useRef[]>(null); + if (ref.current === null) { + // @ts-ignore + ref.current = []; + values.map(value => { + // @ts-ignore + ref.current.push(new Animated.Value(value)); + }); + } + + // effects + useEffect(() => { + if (ref.current) { + values.map((value, index) => { + // @ts-ignore + if (ref.current[index]) { + // update current value + // @ts-ignore + ref.current[index].setValue(value); + } else { + // insert current value + // @ts-ignore + ref.current.push(new Animated.Value(value)); + } + }); + + /** + * if previous animated array has more values than the updated + * array, we will need to set the extra values to the last + * value of the updated array. + */ + if (values.length < ref.current.length) { + const lastValue = values[values.length - 1]; + for (let i = values.length - 1; i <= ref.current.length - 1; i++) { + ref.current[i].setValue(lastValue); + } + } + } + }, [values]); + + return ref.current!; +}; From f3077bc4d4f82e9a3e2545e34453900df8e3576d Mon Sep 17 00:00:00 2001 From: Mo Gorhom Date: Sun, 15 Nov 2020 20:51:39 +0100 Subject: [PATCH 2/2] chore: updated basic example --- example/ios/Podfile.lock | 2 +- example/src/screens/static/BasicExample.tsx | 133 +++----------------- 2 files changed, 20 insertions(+), 115 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 5ad80fb93..ae240e97c 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -481,4 +481,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: aff15ad1e9bd5c910cdc2b575487ce8c56864ae7 -COCOAPODS: 1.9.1 +COCOAPODS: 1.9.3 diff --git a/example/src/screens/static/BasicExample.tsx b/example/src/screens/static/BasicExample.tsx index 3b381477d..efb2c0269 100644 --- a/example/src/screens/static/BasicExample.tsx +++ b/example/src/screens/static/BasicExample.tsx @@ -1,40 +1,32 @@ import React, { useCallback, useMemo, useRef, useState } from 'react'; import { View, StyleSheet } from 'react-native'; -import { useHeaderHeight } from '@react-navigation/stack'; -import Animated, { - interpolate, - concat, - Extrapolate, -} from 'react-native-reanimated'; +import { concat } from 'react-native-reanimated'; import { ReText, useValue } from 'react-native-redash'; -import BottomSheet, { BottomSheetFlatList } from '@gorhom/bottom-sheet'; -import Handle from '../../components/handle'; +import BottomSheet from '@gorhom/bottom-sheet'; import Button from '../../components/button'; +import ContactList from '../../components/contactList'; +import { useSafeArea } from 'react-native-safe-area-context'; const BasicExample = () => { // state const [enabled, setEnabled] = useState(true); + const [dynamicSnapPoint, setDynamicSnapPoint] = useState(450); // hooks const bottomSheetRef = useRef(null); - const headerHeight = useHeaderHeight(); + const { top: topSafeArea } = useSafeArea(); // variables - const snapPoints = useMemo(() => [150, 300, 450], []); + const snapPoints = useMemo(() => [150, dynamicSnapPoint], [dynamicSnapPoint]); const position = useValue(0); // styles - const shadowOverlayStyle = useMemo( + const containerStyle = useMemo( () => ({ - ...styles.shadowOverlay, - opacity: interpolate(position, { - inputRange: [300, 450], - outputRange: [0, 1], - extrapolate: Extrapolate.CLAMP, - }), + ...styles.container, + paddingTop: topSafeArea, }), - // eslint-disable-next-line react-hooks/exhaustive-deps - [] + [topSafeArea] ); // callbacks @@ -44,31 +36,20 @@ const BasicExample = () => { const handleSnapPress = useCallback(index => { bottomSheetRef.current?.snapTo(index); }, []); - const handleClosePress = useCallback(() => { bottomSheetRef.current?.close(); }, []); + const handleIncreaseDynamicSnapPoint = useCallback(() => { + setDynamicSnapPoint(state => state + 50); + }, []); // renders - // const renderHeader = useCallback(() => { - // return ( - // - // Basic Screen - // - // ); - // }, []); - return ( - -