callstack / callstack/react-native-paper

Menu ignores the keyboard when it mounts while the keyboard is already open

Đang mở Phù hợp với người mới
#5,096 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
TypeScript
Star
14.5k
Fork
2.2k
Merge trung bình
5 ngày 23 giờ
Pull request đã merge (30 ngày)
12

Mô tả

### Summary

`Menu` accounts for the on-screen keyboard, but it learns the keyboard height **only from a `keyboardDidShow` event that arrives after it mounts**. iOS does not replay that event for a keyboard that is already open, so a `Menu` that **mounts while the keyboard is already up** keeps a height of `0`, measures against the full window, and lays its items out underneath the keyboard — where they cannot be tapped, and where its own overflow scrolling never engages, because as far as it knows the items fit.

### Current behaviour

`src/components/Menu/Menu.tsx` in 5.14.5:

- L215 — `const keyboardHeightRef = React.useRef(0);`
- L221-228 — `keyboardDidShow` / `keyboardDidHide` set and clear that ref.
- L413-420 — both listeners are attached inside a **mount** effect.
- L343 — `show()` uses the ref: `height: windowLayoutResult.height - keyboardHeightRef.current`

When the keyboard is already visible at mount, no `keyboardDidShow` arrives, the ref stays `0`, and L343 subtracts nothing.

### Why this shows up in practice

Any menu that belongs to a row created while the user is typing. In our app a text field searches for people, and each person added brings a row with its own `Menu`. The field keeps focus (`keyboardShouldPersistTaps="handled"`), so every one of those menus mounts with the keyboard already open.

Two menus on one screen, same bundle and same keyboard state, made the cause unambiguous:

| Menu | Mounts | Keyboard height it believes | Result |
|---|---|---|---|
| Rendered with the screen | Before any keyboard | correct | 9 items, correctly placed clear of the keyboard |
| Rendered into a row added while typing | Keyboard already open | `0` | Ran to y=737 with the keyboard top at y=509; the last 6 items were untappable |

### Steps to reproduce

1. Render a `TextInput` inside a `ScrollView` with `keyboardShouldPersistTaps="handled"`.
2. Render a `Menu` **conditionally**, so that it mounts only after the input has text — for example `{value.length > 0 && }`.
3. Give the menu enough items to reach past the keyboard (about 8 on a 390×844 screen).
4. Focus the input, type a character, then tap the anchor without dismissing the keyboard.

The menu extends under the keyboard. Mount the same menu unconditionally and it positions correctly.

### Expected behaviour

The menu measures against the space the keyboard leaves, whenever it mounted.

### Suggested fix

Read the current keyboard metrics at open time instead of relying only on events. In `show()`:

```diff
setWindowLayout({
- height: windowLayoutResult.height - keyboardHeightRef.current,
+ height:
+ windowLayoutResult.height -
+ (Keyboard.metrics()?.height ?? keyboardHeightRef.current),
width: windowLayoutResult.width,
});
```

`Keyboard.metrics()` returns `undefined` when the keyboard is not shown, so the existing ref stays as the fallback.

**I have not tested this patch.** I worked around the problem in application code instead, and I have not checked how `Keyboard.metrics()` behaves on Android.

### Workaround

Call `Keyboard.dismiss()` before opening the menu. That makes the component's assumption true. It costs nothing in our case, because choosing from a menu is not typing.

### Environment

- react-native-paper 5.14.5
- react-native 0.81.5
- Expo SDK 54
- iOS 26.2, iPhone 16e simulator

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Hướng nghiên cứu

Bắt đầu trong src/components/Menu/Menu.tsx, đọc show() và mount effect đăng ký các keyboard listener. Tái hiện Menu có điều kiện với một TextInput đã được focus như mô tả, sau đó xác minh rằng menu đo chiều cao khả dụng và việc scrolling phần overflow vẫn có thể sử dụng khi bàn phím đang mở. Kiểm tra cách hành vi này được áp dụng trên Android trước khi xem fix là hoàn tất.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
ios, react-native, typescript
Lĩnh vực
frontend, mobile
Loại issue
Lỗi
Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
76/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.