Vertical scrollbar never reappears after resizing window from non-scrollable back to scrollable (ScrollBarComponent::updateVisibility latch)
Maintainer thường phản hồi trong vòng 2 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 76/100
Hướng nghiên cứu
Bắt đầu trong Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp tại ScrollBarComponent::updateVisibility, sau đó lần theo ContentSize, updateLayoutMetrics và updateShowsVerticalScrollIndicator. Tái hiện chuỗi thay đổi kích thước bằng ví dụ ScrollView tối thiểu và tách trạng thái prop của indicator khỏi khả năng hiển thị được tính toán; hoàn tất khi cả thanh dọc và thanh ngang đều xuất hiện lại khi nội dung lớn hơn viewport một lần nữa.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Problem Description
Problem Description
A ScrollView's vertical scrollbar gets permanently latched hidden once the content has fit the viewport, and never comes back even when a later resize makes the content scrollable again.
Sequence:
- Content is larger than the viewport → scrollbar shows (on hover). ✅
- Enlarge the window until the content fits the viewport → scrollbar correctly disappears. ✅
- Shrink the window again so the content is larger than the viewport → scrollbar does not come back. ❌ (mouse-wheel scrolling still works)
Once the bar has been hidden because the content fit the viewport, no later resize shows it again. The only way to recover is to change the showsVerticalScrollIndicator prop.
Root cause
Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp, ScrollBarComponent::updateVisibility (line numbers from the 0.82.5 shipped source):
void updateVisibility(bool visible) noexcept {
if ((m_size.Width <= 0.0f && m_size.Height <= 0.0f) ||
(m_contentSize.Width <= 0.0f && m_contentSize.Height <= 0.0f)) {
m_rootVisual.IsVisible(false);
return;
}
if (!visible) { // (A)
m_visible = false;
m_rootVisual.IsVisible(visible);
return; // early-return: content/size are NOT re-evaluated
}
bool newVisibility = false; // (B) recompute only when visible == true
if (m_vertical) {
newVisibility = (m_contentSize.Height > m_size.Height);
} else {
newVisibility = (m_contentSize.Width > m_size.Width);
}
m_visible = newVisibility;
m_rootVisual.IsVisible(m_visible);
}
The size/content-driven callers pass the previously computed state back in as the visible argument:
// ContentSize(...) -> updateVisibility(m_visible);
// updateLayoutMetrics(...) -> updateVisibility(m_visible);
m_visible defaults to true, and updateShowsVerticalScrollIndicator(value) calls updateVisibility(true|false) from the prop. So m_visible conflates two concepts: the prop showsVerticalScrollIndicator and the computed result (content > viewport).
When the window is enlarged so content fits, branch (B) sets m_visible = false. From then on, every layout/content update calls updateVisibility(m_visible == false), which hits branch (A) and early-returns without re-evaluating content > viewport — so shrinking the window back never re-enables the bar.
Proposed fix
Track the prop separately from the computed visibility and always recompute on size/content changes:
bool m_indicatorEnabled{true}; // set from showsVerticalScrollIndicator
bool m_visible{true}; // computed: (content > viewport) && enabled
void updateVisibility() noexcept {
if ((m_size.Width <= 0.0f && m_size.Height <= 0.0f) ||
(m_contentSize.Width <= 0.0f && m_contentSize.Height <= 0.0f)) {
m_rootVisual.IsVisible(false);
return;
}
const bool scrollable = m_vertical
? (m_contentSize.Height > m_size.Height)
: (m_contentSize.Width > m_size.Width);
m_visible = m_indicatorEnabled && scrollable;
m_rootVisual.IsVisible(m_visible);
}
updateShowsVerticalScrollIndicator(value)→m_indicatorEnabled = value; updateVisibility();ContentSize(...)/updateLayoutMetrics(...)→updateVisibility();
The same applies to the horizontal scrollbar.
Workaround (for app authors)
Toggle showsVerticalScrollIndicator for one frame on every viewport size change, which forces updateShowsVerticalScrollIndicator(true) → updateVisibility(true) to recompute:
const [showVScroll, setShowVScroll] = useState(true);
const onLayout = useCallback(() => {
setShowVScroll(false);
requestAnimationFrame(() => setShowVScroll(true));
}, []);
// <ScrollView showsVerticalScrollIndicator={showVScroll} onLayout={onLayout} />
Steps To Reproduce
- Create/run a Composition (Fabric) RNW 0.82 app whose root renders a vertically scrollable
ScrollView:import { ScrollView, Text } from 'react-native'; export default function App() { return ( <ScrollView showsVerticalScrollIndicator> {Array.from({ length: 60 }).map((_, i) => ( <Text key={i} style={{ height: 40 }}>{`row ${i}`}</Text> ))} </ScrollView> ); } - Launch in a small window → vertical scrollbar appears on hover.
- Enlarge / maximize the window until all rows fit → scrollbar disappears (correct).
- Shrink / restore the window so the rows no longer fit → scrollbar stays hidden, even though the view is scrollable (mouse wheel still scrolls).
Expected Results
After step 4, the vertical scrollbar should be available again (on hover) because the content is once more larger than the viewport.
CLI version
20.0.0
Environment
System:
OS: Windows 11
SDKs:
Windows SDK:
AllowDevelopmentWithoutDevLicense: Enabled
Versions:
- 10.0.22621.0
- 10.0.26100.0
IDEs:
Visual Studio:
- 18.7.11903.348 (Visual Studio Community 2026)
npmPackages:
"@react-native-community/cli":
installed: 20.0.0
wanted: 20.0.0
react:
installed: 19.1.1
wanted: 19.1.1
react-native:
installed: 0.82.1
wanted: 0.82.1
react-native-windows:
installed: 0.82.5
wanted: 0.82.5
Community Modules
From dependencies in package.json:
@expo/react-native-action-sheet: ^4.1.1
@fluentui/react-native: ^0.43.1
@react-native/new-app-screen: 0.82.1
@react-navigation/native: ^7.2.2
@react-navigation/stack: ^7.4.2
@reduxjs/toolkit: ^2.3.0
axios: ^1.9.0
i18next: ^24.2.3
react-i18next: ^15.4.1
react-native-popup-menu: ^0.17.0
react-native-safe-area-context: ^5.5.2
react-native-svg: ^15.12.1
react-redux: ^9.2.0
redux-thunk: ^3.1.0
Note: the bug reproduces with a bare ScrollView and does not depend on any of these modules.
Target React Native Architecture
New Architecture (WinAppSDK) Only
Target Platform Version
10.0.22621
Visual Studio Version
Visual Studio 2026
Build Configuration
Debug
Snack, code example, screenshot, or link to a repository
Minimal repro is the ScrollView snippet under Steps To Reproduce (no community modules required). Repro is a window-resize interaction (enlarge until content fits, then shrink), so it is not reproducible in a Snack — it requires a desktop RNW window.
- Ngôn ngữ chính
- C++
- Star
- 17.4k
- Fork
- 1.2k
- Merge trung bình
- 2 ngày 23 giờ
- Pull request đã merge (30 ngày)
- 16
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của microsoft/react-native-windows
-
Fabric text is drawn with ClearType onto transparent composition surfaces, fringing thin glyphsĐang mởNeeds: Triage :mag:
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/react-native-windows#16340 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
bug Needs: Triage :mag:
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
microsoft/react-native-windows#16321 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
bug Needs: Triage :mag:
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 48/100
microsoft/react-native-windows#16479 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Needs: Triage :mag:
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
microsoft/react-native-windows#16442 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Fabric: activating the window doesn't announce the window or the focused control to a screen readerĐang mởNeeds: Triage :mag:
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
microsoft/react-native-windows#16435 ·
Maintainer thường phản hồi trong vòng 2 ngày
Tất cả issue của microsoft/react-native-windows
Issue tương tự
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 91/100
FujiNetWIFI/fujinet-firmware#2045 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
(S1 - Need confirmation)
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
CleverRaven/Cataclysm-DDA#89159 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area:libnvmpi bug P3
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
gjrtimmer/jetson-nvmpi#33 ·
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug(wasi_crypto): ArrayOutput::pull reports the wrong all-pulled flagCó thể đã có người làm @Yashbhu đã nhận hôm nay. Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 84/100
Maintainer thường phản hồi trong vòng 1 ngày