📱

【React】ボトムシートを作る

2023/01/27に公開

React Spring Bottom Sheetを使用する

インストール

npm i react-spring-bottom-sheet

or

yarn add react-spring-bottom-sheet

コンポーネントの作成

BottomSheet.tsx
import { BottomSheet, BottomSheetRef } from "react-spring-bottom-sheet";
import {
  useRef,
  forwardRef,
  useImperativeHandle,
  ForwardRefRenderFunction,
} from "react";

import "react-spring-bottom-sheet/dist/style.css";

interface Props {
  header: React.ReactNode;
  children: React.ReactNode;
}

export interface ChildHandles {
  fullOpen(): void;
}

const BtmSheetComponent: ForwardRefRenderFunction<ChildHandles, Props> = (
  props,
  ref
) => {
  // ボトムシートの参照
  const sheetRef = useRef<BottomSheetRef>(null);

  // useImperativeHandleを使用することで、親コンポーネントから子コンポーネントのメソッドを呼び出せるようにする
  useImperativeHandle(ref, () => ({
    fullOpen() {
      sheetRef.current?.snapTo(({ snapPoints }) => Math.max(...snapPoints));
    },
  }));
  return (
    <>
      <BottomSheet
        open
        ref={sheetRef}
        // ボトムシートをドラッグしたとき変更できる高さの範囲
        snapPoints={({ minHeight, headerHeight }) => [
          // 最小の高さ
          headerHeight,
          // 最大の高さ
          minHeight,
        ]}
        // オーバーレイを削除して後ろの要素をクリックできるようにする
        blocking={false}
        // ボトムシートのヘッダー部分
        header={props.header}
        skipInitialTransition
      >
        <div
          // 余白を設定
          style={{
            marginLeft: "1rem",
            marginRight: "1rem",
            marginBottom: "1rem",
          }}
        >
          {props.children}
        </div>
      </BottomSheet>
    </>
  );
};
export const BtmSheet = forwardRef(BtmSheetComponent);

Parent.tsx
import { useRef } from "react";
import { BtmSheet, ChildHandles } from "~/components/BottomSheet";

export default function Home() {
  // ボトムシートの子コンポーネントの参照
  const btmSheetRef = useRef<ChildHandles>(null);

  const Header = (
    <div>
      <h3>ヘッダー</h3>
    </div>
  );

  const openSheet = () => {
    // ボトムシートを開く
    btmSheetRef.current?.fullOpen();
  };

  return (
    <>
      <button onClick={openSheet}>open</button>
      <BtmSheet
        // ボトムシートの参照
        ref={btmSheetRef}
        header={Header}
      >
        test
      </BtmSheet>
    </>
  );
}

  • 親コンポーネントの要素からも開くことができるようにしている
  • refからsnapToを操作してopen用の関数を作成している
  • refを通して作成した関数を呼び出している
    シンプルすぎるサンプル

注意

なんか動きがおかしいと思っていたら、
メイン要素がスクロールできない問題がずっとあるみたい...
メイン要素をスクロールさせたいなら、
サンプルのようにヘッダー常時表示はできなそう...
https://github.com/stipsan/react-spring-bottom-sheet/issues/231

Discussion