Skip to content

unstable_headerRightItems: state: 'on' checkmark not displayed for items in the second of two sibling nested submenus #3973

@TimmNL

Description

@TimmNL

Description

When two nested submenus are rendered as siblings inside an inline-grouped menu under unstable_headerRightItems, action items in the first submenu correctly display their state: 'on' checkmark, but action items in the second submenu show no checkmark — even though the JS-side data is structurally identical between the two submenus.

This appears related to the flat-index identifier scheme that issue #3606 and PR #3762 addressed for onPress handler routing. It looks like the same flat-index identity is also used to associate state with each item, so the second submenu's state is silently lost on the native side.

Steps to reproduce

  1. Create a screen using react-native-screens with <Stack.Screen options={{ unstable_headerRightItems: () => [...] }} />.
  2. Configure a type: 'menu' item that contains an inline: true wrapper submenu, which itself contains two sibling submenus ("Sort" and "Group"). Each child submenu has a list of type: 'action' items, with state: 'on' set on the matching item:
{
  type: 'menu',
  label: 'More',
  icon: { type: 'sfSymbol', name: 'ellipsis' },
  menu: {
    items: [
      {
        type: 'submenu',
        label: '',
        inline: true,
        items: [
          {
            type: 'submenu',
            label: 'Sort',
            icon: { type: 'sfSymbol', name: 'arrow.up.arrow.down' },
            items: [
              { type: 'action', label: 'Manual',   state: 'off', onPress: () => {} },
              { type: 'action', label: 'Due date', state: 'on',  onPress: () => {} },
              { type: 'action', label: 'Priority', state: 'off', onPress: () => {} },
            ],
          },
          {
            type: 'submenu',
            label: 'Group',
            icon: { type: 'sfSymbol', name: 'square.3.layers.3d' },
            items: [
              { type: 'action', label: 'None',      state: 'on',  onPress: () => {} },
              { type: 'action', label: 'Goal',      state: 'off', onPress: () => {} },
              { type: 'action', label: 'Life area', state: 'off', onPress: () => {} },
            ],
          },
        ],
      },
    ],
  },
}
  1. Open the "More" menu on the header → tap "Sort" → checkmark is shown next to "Due date" ✅
    Back to "More" menu → tap "Group" → no item has a checkmark ❌, even though "None" has state: 'on'.
    when switching between the 2, the checkmark seems to move from 1 to the other in the reproduction. In my case, both always have a state with a checkmark.

Snack or a link to a repository

https://snack.expo.dev/@handsometim/react-native-screens-unstable_headerrightitems-checkmark-not-displayed-reproduction

Screens version

4.24.0

React Native version

0.83.2

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Expo managed workflow

Architecture

Fabric (New Architecture)

Build type

Release mode

Device

Real device

Device model

iPhone 15 pro

Acknowledgements

Yes

Metadata

Metadata

Assignees

Labels

platform:iosIssue related to iOS part of the libraryrepro-providedA reproduction with a snack or repo is provided

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions