1 year ago

#351492

test-img

universe11

own bottomsheet is every time on screen, performance problems?

I Created a bottom sheet with reanimated and gesture handler.

So it works fine, but if I close the modal, the modal is always open but you dont see it, it is under the screen. Get I performance problems or is that bad ?

import { Dimensions, Pressable, StyleSheet, Text, View } from 'react-native'
import React, { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
import { FlatList, Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { Extrapolate, interpolate, runOnJS, useAnimatedStyle, useDerivedValue, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
import { FontAwesome5 } from '@expo/vector-icons';
import { Button } from '../Button';

const { height } = Dimensions.get('screen');

interface BottomSheetProps {};

export interface BottomSheetPropsRef {
  open: () => void;
}

const BottomSheet = forwardRef<BottomSheetPropsRef, BottomSheetProps>(({ heightProp }, ref) => {
  
  const newRef = useRef(false);

  const translateY = useSharedValue(0);

  const context = useSharedValue(0);

  const [pointer, setPointer] = useState(false);
  
  const scrollTo = useCallback((dest: number) => {
    'worklet'
    translateY.value = withTiming(dest, { duration: 250 });
  }, []);
  
  const open = useCallback(() => {
    'worklet'
    translateY.value = withTiming(-heightProp, { duration: 250 }, (isFinished) => {
      runOnJS(setPointer)(true);
    });
  }, []);

  useImperativeHandle(ref, () => ({ open }), [open]);

  const panGesture = Gesture.Pan()
  .onStart((e) => {
    context.value = translateY.value;
  })
  .onUpdate((e) => {
    if(translateY.value !== 0) {
      translateY.value = e.translationY + context.value;
      translateY.value = Math.max(translateY.value, -heightProp);
    }
  })
  .onEnd(() => {
    if(translateY.value >= -heightProp / 1) {
      translateY.value = withTiming(0, { duration: 50 }, (isFinished) => {
        runOnJS(setPointer)(false);
      });
    } else {
      scrollTo(-heightProp)
    }
  });

  const rBottomSheet = useAnimatedStyle(() => {
    return {
      transform: [{ translateY: translateY.value }]
    }
  });

  const rView = useAnimatedStyle(() => {
  // const opacity = interpolate(translateY.value, [-height, height], [0, 1], Extrapolate.CLAMP);
    const backgroundColor = interpolate(translateY.value, [0, -heightProp], [0, 0.6])
    return {
      backgroundColor: `rgba(0,0,0,${backgroundColor})`
    }
  });

  const tapGesturEv = Gesture.Tap().onStart((e) => {
    translateY.value = withTiming(0, { duration: 80 }, (isFinished) => {
      if(isFinished) {
        runOnJS(setPointer)(false)
      }
    });

  });

  const flexGrow = useAnimatedStyle(() => {
    const flexGrow = interpolate(translateY.value, [0, 1], [0, 1]);
    const backgroundColor = interpolate(translateY.value, [0, -heightProp], [0, 0.4])
    return {
      flexGrow,
      backgroundColor: `rgba(0,0,0,${backgroundColor})`
    }
  });


  const style = useMemo(() => [flexGrow], [flexGrow]);

  return (
<Animated.View pointerEvents={pointer ? 'auto' : 'none'} style={[{ ...StyleSheet.absoluteFillObject, flex: 1, position: 'absolute', zIndex: 100 }]}>

  <GestureDetector gesture={tapGesturEv}>
    <Animated.View style={[{ zIndex: -1, backgroundColor: 'grey'}, style]} />
  </GestureDetector> 

    {/*  HERE Starts the bottom Sheet, the above is the overlay */ }
      <GestureDetector gesture={panGesture}>
        <Animated.View style={[s.bottomSheet, rBottomSheet, { height: heightProp }]}>
        <View style={s.line} />
          <View style={{flex: 1, backgroundColor: '#fff', justifyContent: 'center', alignItems: 'center'}}>
            <Button>
              <FontAwesome5 name="male" size={24} color="black" />
              <Text>asdsas</Text>
            </Button>
            <Button>
              <FontAwesome5 name="male" size={24} color="black" />
              <Text></Text>
            </Button>
          </View>
        </Animated.View>
      </GestureDetector>
      
  </Animated.View>
  )
});

export default memo(BottomSheet);

App.tsx

...
<BottomSheet ref={modal} />
...

I can set a state to hide the modal but the problem is then its lag when I open the modal exp:

const [bottomSheet, setBottomSheet] = useState(false);
const bottomSheetModal = useRef();

const openBottomSheet = () => {
  setBottomSheet(true);
  bottomSheetModal.current?.open();
};

{
  bottomSheet && (<BottomSheet ref={bottomSheetModal} />)
}

So whats you opinion about this ?

do you have tips for me ?

react-native

expo

react-native-reanimated

react-native-gesture-handler

react-native-reanimated-v2

0 Answers

Your Answer

Accepted video resources