☰
React Native Bottom Sheet Modal Props 深度解析:从 name 到容器定制的完整配置指南
2026/9/25 5:37:31 网站建设 项目流程
  • 前端
  • 移动开发
  • UI组件
  • 跨平台

【免费下载链接】react-native-bottom-sheet

A performant interactive bottom sheet with fully configurable options 🚀

项目地址:https://gitcode.com/gh_mirrors/re/react-native-bottom-sheet
点击查看免费下载

Bottom Sheet Modal是@gorhom/bottom-sheet在Bottom Sheet之上包装/装饰出的模态化组件,它继承了底部弹层全部功能,并额外提供模态呈现(present/dismiss)、栈式多弹层管理(stack sheet modals)等能力。本指南以 v4 版本modal/props.md文档为骨架,结合仓库源码,系统讲解BottomSheetModal的独有 props——name、stackBehavior、enableDismissOnClose、onDismiss、containerComponent的类型、默认值、底层实现与典型使用场景。读完你将掌握:如何为每个模态命名并定向管理、如何通过push/switch/replace三种栈行为编排多弹层、如何在关闭时自动卸载并监听onDismiss,以及如何用containerComponent配合FullWindowOverlay把弹层提升到应用最顶层。

一、Modal 是什么:包装在 Bottom Sheet 之上的呈现层

在深入 props 之前,先明确Bottom Sheet Modal的定位。根据 modal/index.mdx,它是Bottom Sheet的 wrapper/decorator(包装/装饰器),提供其全部功能并叠加"模态呈现"能力:平滑的挂载(mounting)动画、以及受 Apple Maps sheet modals 启发的栈式 sheet modal支持。

从源码看,这一包装关系非常直观:在 src/components/bottomSheetModal/BottomSheetModal.tsx 中,组件内部维护了一个BottomSheet的 ref,并将外层接收到的snapPoints、index、enablePanDownToClose、animateOnMount等透传给内层<BottomSheet>:

<BottomSheet {...bottomSheetProps} ref={bottomSheetRef} index={index} snapPoints={snapPoints} enablePanDownToClose={enablePanDownToClose} animateOnMount={animateOnMount} containerHeight={containerHeight} containerOffset={containerOffset} onChange={handleBottomSheetOnChange} onClose={handleBottomSheetOnClose} onAnimate={handleBottomSheetOnAnimate} $modal={true} > {typeof Content === 'function' ? <Content data={data} /> : Content} </BottomSheet>

同时,BottomSheetModal通过useImperativeHandle暴露了完整的命令式 API——既有继承自 Bottom Sheet 的snapToIndex、snapToPosition、expand、collapse、close、forceClose,也有模态专属的dismiss、present(详见 modal/methods.md):

// src/components/bottomSheetModal/BottomSheetModal.tsx useImperativeHandle(ref, () => ({ // sheet methods(继承自 Bottom Sheet) snapToIndex, snapToPosition, expand, collapse, close, forceClose, // modal methods(新增) dismiss: handleDismiss, present: handlePresent, // internal(供 Provider 栈管理使用) minimize: handleMinimize, restore: handleRestore, }));

props 继承关系:BottomSheetModal继承Bottom Sheet的全部 props(snapPoints、index、onChange、enablePanDownToClose、自定义 handle/backdrop 等,参见 version-4/props.md),仅排除animateOnMount与containerHeight这两个由 Modal 内部接管的值(containerHeight由 Provider 统一注入,animateOnMount在 Modal 语义下不再适用)。在此基础上,Modal 引入了自己的 5 个专属配置项,下面逐一展开。

二、Configuration:三个行为配置项

2.1 name —— 给模态一个可寻址的标识

typedefaultrequired
stringgenerated unique keyNO

name用于标识模态,方便后续定向管理(例如配合useBottomSheetModal的dismiss(key)精确关闭指定模态)。

从源码可以印证它的实现与用途。在 src/components/bottomSheetModal/BottomSheetModal.tsx 中:

const key = useMemo(() => name || `bottom-sheet-modal-${id()}`, [name]);

即:传入name则以其为 key;未传入时自动生成唯一 key(id()定义于 src/utilities/id.ts)。这个key同时充当了@gorhom/portal的 portal 名称,以及 Modal Provider 栈队列(sheetsQueueRef)中该弹层的索引键,从而实现"按名定位"。

实践中建议:同一界面若存在多个BottomSheetModal(例如评论弹层 + 分享弹层),务必为它们分配不同的name,否则栈管理和定向 dismiss 会相互干扰。

2.2 stackBehavior —— 定义模态挂载时的栈行为

说明:文档中标注"Available only on v3, for now"是历史遗留提示;在 v4 中该能力已完整支持。

stackBehavior决定当一个新的 Modal 挂载(present)时,当前已呈现的 Modal 该如何处理:

  • push—— 将新模态直接挂载到当前模态之上(两者都可见,形成堆叠);
  • switch—— 先将当前模态最小化(minimize),再挂载新模态(默认行为);
  • replace—— 先关闭(dismiss)当前模态,再挂载新模态。
typedefaultrequired
'push' \| 'switch' \| 'replace''switch'NO

源码佐证:合法取值定义在 src/constants.ts 的MODAL_STACK_BEHAVIOR常量中;默认值'switch'与类型定义BottomSheetModalStackBehavior位于 src/components/bottomSheetModal/constants.ts 与 types.d.ts。

栈行为真正落地在 src/components/bottomSheetModalProvider/BottomSheetModalProvider.tsx 的handleMountSheet中:

const currentMountedSheet = _sheetsQueue[_sheetsQueue.length - 1]; if (currentMountedSheet && !currentMountedSheet.willUnmount) { if (stackBehavior === MODAL_STACK_BEHAVIOR.replace) { currentMountedSheet.ref?.current?.dismiss(); } else if (stackBehavior === MODAL_STACK_BEHAVIOR.switch) { currentMountedSheet.ref?.current?.minimize(); } }

可以看到:push不触碰当前模态直接入栈;switch调用当前模态内部的minimize()(通过 BottomSheetModal.tsx 的handleMinimize记录restoreIndexRef后执行close());replace则直接dismiss()当前模态。而当你关闭/收起栈顶模态后,Provider 的handleUnmountSheet/handleWillUnmountSheet会自动对栈中前一个被最小化的模态调用restore(),恢复其原有位置——这正是"栈式"体验的关键闭环。

典型使用:需要"二级详情页"式体验(如地图 App 中列表 → 详情)时用replace;需要"通知堆叠"式体验时用push;默认的switch则适用于大多数"先让位、再登场"的场景。

2.3 enableDismissOnClose —— 关闭即卸载

typedefaultrequired
booleantrueNO

当模态关闭(closed)时是否将其卸载(unmount)。默认true,即弹层一旦关闭就会从 React 树中移除,释放内存与原生视图。

源码逻辑位于 BottomSheetModal.tsx 的handleBottomSheetOnClose:

const handleBottomSheetOnClose = useCallback(function handleBottomSheetOnClose() { if (minimized.current) return; // 被 switch 最小化时不卸载 if (enableDismissOnClose) { unmount(); } }, [enableDismissOnClose, unmount]);

而unmount()会依次:重置内部变量 →unmountSheet(key)从 Provider 栈中移除 →unmountPortal(key)销毁 portal → 将mount状态复位(setState(INITIAL_STATE))→触发onDismiss回调。

设置enableDismissOnClose={false}时,弹层关闭后仍保留挂载状态(内部currentIndexRef回到-1的关闭位),适合希望保留弹层内容状态、避免重复重建的场景;但要注意它与onDismiss(只在真正卸载时触发)的联动差异。

三、Callbacks:onDismiss —— 卸载时的收尾回调

type onDismiss = () => void;
typedefaultrequired
functionnullNO

onDismiss在模态**被卸载(dismissed/unmounted)**时触发。注意它与onClose(Bottom Sheet 的关闭回调,仅表示动画走到关闭位)的区别:onDismiss语义更重,代表模态从视图树中彻底移除。

从源码看,它是在unmount()的收尾阶段被调用的:

const unmount = useCallback(function unmount() { resetVariables(); unmountSheet(key); unmountPortal(key); if (_mounted) { setState(INITIAL_STATE); } // fire `onDismiss` callback if (_providedOnDismiss) { _providedOnDismiss(); } }, [key, resetVariables, unmountSheet, unmountPortal, _providedOnDismiss]);

典型使用:在onDismiss中做数据刷新、埋点统计、或清理依赖模态的临时状态。例如用户在弹层内完成了某项操作后手动下滑关闭,此时触发onDismiss通知列表页刷新。

四、Components:containerComponent —— 容器定制与 FullWindowOverlay

typedefaultrequired
React.ReactNodeundefinedNO

containerComponent用于替换模态的容器组件,核心场景是:当使用react-native-screens的FullWindowOverlay时,将 bottom sheet 放置到应用最顶层,从而覆盖其他 Screen 之上的内容(对应 gorhom/react-native-bottom-sheet#832 所述问题)。

源码实现上,ContainerComponent被包裹在 portal 内部、BottomSheet之外:

<Portal ...> <ContainerComponent key={key}> <BottomSheet ... /> </ContainerComponent> </Portal>

文档中表格将该 prop 类型写作React.ReactNode,而仓库 types.d.ts 的实际类型定义更精确:containerComponent?: React.ComponentType<React.PropsWithChildren>,即应传入一个组件类型(如FullWindowOverlay),而非一个 JSX 实例。传自定义容器时需注意:容器需要接收并正确渲染其children(即内部的 BottomSheet),并保证布局尺寸正常。

在 example/src/screens/integrations/map 中可以看到这类容器定制的实践参考(BlurredBackground、LocationDetailsBottomSheet等组件展示了与全屏背景、详情弹层组合的写法)。

五、组合实战:完整可运行的用法示例

以下示例继承自 modal/usage.md 并加以扩展,演示了 Provider 包裹、ref 声明、present()呈现、onChange监听、以及专属 props 的组合使用:

import React, { useCallback, useMemo, useRef } from 'react'; import { View, Text, StyleSheet, Button } from 'react-native'; import { BottomSheetModal, BottomSheetModalProvider, BottomSheetModalMethods, } from '@gorhom/bottom-sheet'; const App = () => { // ref const bottomSheetModalRef = useRef<BottomSheetModalMethods>(null); // variables const snapPoints = useMemo(() => ['25%', '50%'], []); // callbacks const handlePresentModalPress = useCallback(() => { bottomSheetModalRef.current?.present(); }, []); const handleSheetChanges = useCallback((index: number) => { console.log('handleSheetChanges', index); }, []); const handleOnDismiss = useCallback(() => { console.log('Modal dismissed & unmounted'); }, []); // renders return ( <BottomSheetModalProvider> <View style={styles.container}> <Button onPress={handlePresentModalPress} title="Present Modal" color="black" /> <BottomSheetModal ref={bottomSheetModalRef} name="main-modal" stackBehavior="switch" enableDismissOnClose={true} index={1} snapPoints={snapPoints} onChange={handleSheetChanges} onDismiss={handleOnDismiss} > <View style={styles.contentContainer}> <Text>Awesome 🎉</Text> </View> </BottomSheetModal> </View> </BottomSheetModalProvider> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 24, justifyContent: 'center', backgroundColor: 'grey', }, contentContainer: { flex: 1, alignItems: 'center', }, }); export default App;

要点回顾:

  • 必须使用BottomSheetModalProvider包裹:Modal 的挂载、栈管理与containerHeight注入都依赖该 Provider(见 src/components/bottomSheetModalProvider/BottomSheetModalProvider.tsx);
  • 调用present()而非直接渲染:Modal 初始不挂载(mount: false),必须通过 ref 调用present()触发挂载与呈现动画;present还可接收可选参数data传入弹层内容(若 children 是函数组件({ data }) => ...则直接接收);
  • 滚动内容:如需在弹层内使用 FlatList / ScrollView / SectionList,请改用BottomSheetFlatList、BottomSheetScrollView、BottomSheetSectionList等可滚动组件(参见 version-4/scrollables.md),以保证手势联动正常。

六、配套能力:useBottomSheetModal 与命令式 API

虽然props.md本身只讲解配置项,但要完整使用 Modal 的 props 效果(尤其name与stackBehavior),离不开两个配套入口,这里一并给出(依据 modal/hooks.md 与 modal/methods.md)。

6.1 useBottomSheetModal —— 从任意组件操控模态

该 hook 在BottomSheetModalProvider内的任何组件中可用,提供模态专属能力(Sheet 自身能力请查看 version-4/hooks.md):

import React from 'react'; import { View, Button } from 'react-native'; import { useBottomSheetModal } from '@gorhom/bottom-sheet'; const SheetContent = () => { const { dismiss, dismissAll } = useBottomSheetModal(); return ( <View> <Button title="Dismiss" onPress={() => dismiss('main-modal')} /> <Button title="Dismiss All" onPress={dismissAll} /> </View> ); };
  • dismiss(key?: string):按name/key 定向关闭某个模态;不传 key 时关闭最后呈现(栈顶)的模态;
  • dismissAll():关闭并卸载所有已呈现的模态。

其底层实现在 BottomSheetModalProvider.tsx 的handleDismiss/handleDismissAll中——前者按name在sheetsQueueRef中查找并调用对应 ref 的dismiss(),这也再次印证了nameprop 的价值。

6.2 模态专属方法:present / dismiss

通过 ref 可直接调用(除继承自 Bottom Sheet 的 6 个方法外):

type present = ( // Data to be passed to the modal. data?: any ) => void; type dismiss = ( // AnimationConfigs snap animation configs. animationConfigs?: WithSpringConfig | WithTimingConfig ) => void;
  • present(data?):挂载并呈现模态到初始 snap point,可选地传入数据;
  • dismiss(animationConfigs?):关闭并卸载模态,可自定义关闭动画配置(支持 Reanimated 的弹簧/时序配置)。

七、总结:五张表速查

Prop类型默认值必填作用
namestring自动生成唯一 key否标识模态,用于定向 dismiss 与栈管理
stackBehavior'push' \| 'switch' \| 'replace''switch'否新模态挂载时对当前模态的处理策略
enableDismissOnClosebooleantrue否关闭时是否卸载模态
onDismiss() => voidnull否模态被卸载时触发的回调
containerComponentReact.ComponentType<React.PropsWithChildren>undefined否自定义容器,典型用于FullWindowOverlay顶层呈现

关键源码索引(便于继续深入):

  • Modal 组件实现:src/components/bottomSheetModal/BottomSheetModal.tsx
  • Props 类型与默认值:src/components/bottomSheetModal/types.d.ts、src/components/bottomSheetModal/constants.ts
  • 栈管理核心:src/components/bottomSheetModalProvider/BottomSheetModalProvider.tsx
  • 栈行为取值常量:src/constants.ts
  • 示例应用:example/src/screens/modal

至此,你已经掌握BottomSheetModal全部专属 props 的语义、默认值、源码路径与实战组合方式。在此基础上,按需搭配useBottomSheetModal的dismiss/dismissAll、present(data)传参以及BottomSheetFlatList等滚动组件,即可构建出接近原生体验、支持多弹层栈编排的完整模态体系。

  • 前端
  • 移动开发
  • UI组件
  • 跨平台

【免费下载链接】react-native-bottom-sheet

A performant interactive bottom sheet with fully configurable options 🚀

项目地址:https://gitcode.com/gh_mirrors/re/react-native-bottom-sheet
点击查看免费下载

相关推荐

上一篇:[你的MCP服务器名称] 安装指南
下一篇:.NET Core安装指南:多平台部署

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询