📱
【React】ボトムシートを作る
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を通して作成した関数を呼び出している
シンプルすぎるサンプル
注意
なんか動きがおかしいと思っていたら、
メイン要素がスクロールできない問題がずっとあるみたい...
メイン要素をスクロールさせたいなら、
サンプルのようにヘッダー常時表示はできなそう...
Discussion