[React-native] Bottom-Sheet 만들기

seoleem Lee·2024년 9월 12일

개요

배x의 민x 어플을 보면, 사진 업로드 시 카메라/앨범 여부를 물어보며 슬라이드 형식으로 아래서 올라오는 창을 본 적이 있을 것이다.

현재 개발 중인 프로젝트 또한 다음과 같은 기능을 요구하기에, 해당 기능을 구현할 수 있는 라이브러리를 찾아다녔다…

서치를 통해 다음과 같은 기능을 제공하는 곳을 찾았다!

React Native Bottom Sheet | Gorhom UI

현재 expo를 사용중이기 때문에, expo 기준으로 작성될 예정

자세한 설치법은 사이트의 Installation 부분을 따르길 바란다.

1. 종속성 설치

1) dependencies 추가

npx expo install react-native-reanimated react-native-gesture-handler

  • 해당 기능을 사용하기 위해선 프로젝트 터미널에 다음 내용을 install 한다.

2) 래핑하기

React Native Gesture Handler는 설치를 마무리하기 위해 추가 단계가 필요합니다. React Native Gesture Handler ^2로 업그레이드한 후에 는 앱을 래핑 해야 합니다.

Installation | React Native Gesture Handler

아까 설치했던 내용 중 react-native-gesture-handler 부분에서 요구하는 것 같다.

일단 시키는 대로 상단에

import { GestureHandlerRootView } from 'react-native-gesture-handler';

작성 후 App.js의 상단을 <GestureHandlerRootView> 로 감싼다.

3) react-native-reanimated 추가 설정하기

  • bavel.config.js 파일에 설정을 추가해야 사용할 수 있다.
  module.exports = {
    presets: [
      ... // don't add it here :)
    ],
    plugins: [
      ...
      'react-native-reanimated/plugin',
    ],
  };

react-native-reanimated/plugin 는 마지막에 나열해야 한다.

4) 디렉토리 의 네이티브 코드 업데이트

npx expo prebuild

  • 터미널에 다음과 같이 작성하여 변경 사항을 저장해준다.

이와 같은 과정이 끝났다면, 이제 바텀 시트를 “설치할 준비”가 완료되었다!

…놀랍게도 설치 준비 과정이다.

이제 터미널에 다음과 같이 입력하자.

yarn add @gorhom/bottom-sheet@^4

설치가 완료되었다면, 이제 사용할 수 있다.


Bottom sheet 사용해보기

공식 페이지의 useage 탭에 있는 코드를 그대로 가져와 사용해보자.

import React, { useCallback, useMemo, useRef } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';

const App = () => {
  // ref
  const bottomSheetRef = useRef<BottomSheet>(null);

  // callbacks
  const handleSheetChanges = useCallback((index: number) => {
    console.log('handleSheetChanges', index);
  }, []);

  // renders
  return (
    <View style={styles.container}>
      <BottomSheet
        ref={bottomSheetRef}
        onChange={handleSheetChanges}
      >
        <BottomSheetView style={styles.contentContainer}>
          <Text>Awesome 🎉</Text>
        </BottomSheetView>
      </BottomSheet>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: 'grey',
  },
  contentContainer: {
    flex: 1,
    alignItems: 'center',
  },
});

export default App;

이 코드를 그대로 긁어와 사용하려고 봤더니 다음과 같은 문제가 있었다.

  1. 타입 스크립트 호환
    • 나는 nomal js를 사용중이기 때문에 index: number 과 같은 부분은 사용할 수 없었다. 이런 부분에 있어 수정이 필요했다.
  2. snapPoints
    • 추측하건대, BottomSheet의 위치를 기억하기 위해 사용되는 변수 같다. 그러나 공식 문서에 해당 부분이 누락되어 오류가 발생했다. 다른 사람들이 작성한 내용을 참고해 수정한다.
  3. useCallback의 존재 의의?
    • 추후 기능이 추가된다면 사용할 거 같지만 현재로선 딱히? 과감히 지워줬다.

그렇게 수정한 코드는 다음과 같다.

import React, { useCallback, useMemo, useRef } from "react";
import { View, Text, StyleSheet } from "react-native";
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";

export default function ReadingScreen() {
  // ref
  const bottomSheetRef = useRef(null);

  // variables
  const snapPoints = useMemo(() => ["50%"], []);

  // callbacks
  const handleSheetChanges = useCallback((index) => {
    console.log("handleSheetChanges", index);
  }, []);

  // renders
  return (
    <View style={styles.container}>
      <BottomSheet
        ref={bottomSheetRef}
        index={0}
        snapPoints={snapPoints}
        onChange={handleSheetChanges}
      >
        <View style={styles.contentContainer}>
          <Text>Awesome 🎉</Text>
        </View>
      </BottomSheet>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: "grey",
  },
  contentContainer: {
    flex: 1,
    alignItems: "center",
  },
});

이렇게 작성하니 일단 작동은 잘 된다!

그러나 원하는 바와 달라 계속 고군분투 할 거 같다…

다음에 계속ㅋ

profile
한 줄의 코드로 세상을 변화 시키고 싶은 개발자 이서림 입니다.

0개의 댓글