@exodus/react-native-menu

中文文档
2.0.0-exodus-5发布于 2026/01/02MITTypeScriptESM + CJS零依赖近 30 天下载 1万

UIMenu component for react-native (iOS only)

原始使用文档
文档目录16 节
  1. Installation
  2. Installing on iOS with React Native 0.63 and above
  3. Linking
  4. Usage
  5. Declarative usage
  6. Reference
  7. Props
  8. title (iOS only)
  9. shouldOpenOnLongPress
  10. actions
  11. themeVariant (iOS only)
  12. onPressAction
  13. Events
  14. Testing with Jest
  15. Contributing
  16. License

@exodus/react-native-menu

Supports iOSGithub Action Badge npm

iOS14+ UIMenu components for react-native. Falls back to ActionSheet for versions below iOS14.

iOS 14+iOS 13

Installation

via npm:

npm install @exodus/react-native-menu

via yarn:

yarn add @exodus/react-native-menu

Installing on iOS with React Native 0.63 and above

There is an issue(https://github.com/facebook/react-native/issues/29246) causing projects with this module to fail on build on React Native 0.63 and above. This issue may be fixed in future versions of react native. As a work around, look for lines in [YourPrject].xcodeproj under LIBRARY_SEARCH_PATHS with "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", and change swift-5.0 to swift-5.3.

Linking

The package is automatically linked when building the app. All you need to do is:

npx pod-install

Usage

import { MenuView, MenuComponentRef } from "@exodus/react-native-menu";

const App = () => {
  const menuRef = useRef < MenuComponentRef > null;
  return (
    <View style={styles.container}>
      <MenuView
        ref={menuRef}
        title="Menu Title"
        onPressAction={({ nativeEvent }) => {
          console.warn(JSON.stringify(nativeEvent));
        }}
        actions={[
          {
            id: "add",
            title: "Add",
            titleColor: "#2367A2",
            image: "plus",
            imageColor: "#2367A2",
            subactions: [
              {
                id: "nested1",
                title: "Nested action",
                titleColor: "rgba(250,180,100,0.5)",
                subtitle: "State is mixed",
                image: "heart.fill",
                imageColor: "rgba(100,200,250,0.3)",
                state: "mixed",
              },
              {
                id: "nestedDestructive",
                title: "Destructive Action",
                attributes: {
                  destructive: true,
                },
                image: "trash",
              },
            ],
          },
          {
            id: "share",
            title: "Share Action",
            titleColor: "#46F289",
            subtitle: "Share action on SNS",
            image: "square.and.arrow.up",
            imageColor: "#46F289",
            state: "on",
          },
          {
            id: "destructive",
            title: "Destructive Action",
            attributes: {
              destructive: true,
            },
            image: "trash",
          },
        ]}
        shouldOpenOnLongPress={false}
      >
        <View style={styles.button}>
          <Text style={styles.buttonText}>Test</Text>
        </View>
      </MenuView>
    </View>
  );
};

Declarative usage

It's also possible to obtain the action is a more React-ish, declarative fashion. Refer to the react-to-imperative package, and see an example here.

Reference

Props

title (iOS only)

The title of the menu.

TypeRequired
stringYes

shouldOpenOnLongPress

Boolean determining if menu should open after long press or on normal press

TypeRequired
booleanNo

actions

Actions to be displayed in the menu.

TypeRequired
MenuAction[]Yes

themeVariant (iOS only)

String to override theme of the menu. If you want to control theme universally across your app, see this package.

TypeRequired
enum('light', 'dark')No

MenuAction

Object representing Menu Action.

export type MenuAction = {
  /**
   * Identifier of the menu action.
   * The value set in this id will be returned when menu is selected.
   */
  id?: string;
  /**
   * The action's title.
   */
  title: string;
  /**
   * (iOS14+ only)
   * An elaborated title that explains the purpose of the action.
   * @platform iOS
   */
  subtitle?: string;
  /**
   * The attributes indicating the style of the action.
   */
  attributes?: MenuAttributes;
  /**
   * (iOS14+ only)
   * The state of the action.
   * @platform iOS
   */
  state?: MenuState;
  /**
   * (iOS13+ only)
   * - The action's image.
   * - Allows icon name included in SF Symbol
   * @example
   * image="plus"
   */
  image?: string;
  /**
   * (iOS13+ only)
   * - The action's image color.
   */
  imageColor?: number | ColorValue;
  /**
   * (iOS14+ only)
   * - Actions to be displayed in the sub menu
   */
  subactions?: MenuAction[];
};

MenuAttributes

The attributes indicating the style of the action.

type MenuAttributes = {
  /**
   * An attribute indicating the destructive style.
   */
  destructive?: boolean;
  /**
   * An attribute indicating the disabled style.
   */
  disabled?: boolean;
  /**
   * An attribute indicating the hidden style.
   */
  hidden?: boolean;
};

MenuState

The state of the action.

/**
 * The state of the action.
 * - off: A constant indicating the menu element is in the "off" state.
 * - on: A constant indicating the menu element is in the "on" state.
 * - mixed: A constant indicating the menu element is in the "mixed" state.
 */
type MenuState = "off" | "on" | "mixed";

onPressAction

Callback function that will be called when selecting a menu item. It will contain id of the given action.

TypeRequired
({nativeEvent}) => voidNo

Events

onCloseMenu

Callback function that will be called when the menu is dismissed. This event fires at the start of the dismissal, before any animations complete.

TypeRequired
() => voidNo

onOpenMenu

Callback function that will be called when the menu is opened. This event fires right before the menu is displayed.

TypeRequired
() => voidNo

Example usage:

<MenuView
  onOpenMenu={() => {
    console.log("Menu was opened");
  }}
  onCloseMenu={() => {
    console.log("Menu was closed");
  }}
>
  <View>
    <Text>Open Menu</Text>
  </View>
</MenuView>

Testing with Jest

In some cases, you might want to mock the package to test your components. You can do this by using the jest.mock function.

import type { MenuComponentProps } from "@exodus/react-native-menu";

jest.mock("@exodus/react-native-menu", () => ({
  MenuView: jest.fn((props: MenuComponentProps) => {
    const React = require("react");

    class MockMenuView extends React.Component {
      render() {
        return React.createElement(
          "View",
          { testID: props.testID },
          props.actions.map((action) =>
            React.createElement("Button", {
              key: action.id,
              title: action.title,
              onPress: () => {
                if (action.id && props?.onPressAction) {
                  props.onPressAction({ nativeEvent: { event: action.id } });
                }
              },
              testID: action.id,
            })
          ),
          this.props.children
        );
      }
    }

    return React.createElement(MockMenuView, props);
  }),
}));

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

版本与发布记录

@exodus/react-native-menu 共发布 6 个版本,首次发布于 2025/10/29;过去 12 个月发布了 2 个版本。

版本发布日期距今
2.0.0-exodus-5latest2026/01/0210 个月前
2.0.02026/01/0210 个月前
2.0.0-exodus-4exodus-42025/10/291 年前
2.0.0-exodus-3exodus-32025/10/291 年前
2.0.0-exodus-2exodus-22025/10/291 年前
2.0.0-exodus-1exodus-12025/10/291 年前

关于 @exodus/react-native-menu 的常见问题

@exodus/react-native-menu 是什么?

UIMenu component for react-native (iOS only)

如何安装 @exodus/react-native-menu?

在项目目录运行 npm install @exodus/react-native-menu,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(*)、react-native(*)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@exodus/react-native-menu 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@exodus/react-native-menu 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@exodus/react-native-menu 可以商用吗?

@exodus/react-native-menu 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@exodus/react-native-menu 的下载量有多少?

根据 npm 官方下载统计,@exodus/react-native-menu 在 2026/10/14 – 2026/11/12 这 30 天内被下载 10,395 次,日均约 347 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@exodus/react-native-menu 还在维护吗?

最新版本 2.0.0-exodus-5 发布于 2026/01/02(10 个月前);至今共发布 6 个版本,其中过去 12 个月发布了 2 个;首次发布于 2025/10/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。