Environment
| Package |
Version |
| react-native-pager-view |
8.0.0 – 8.0.2 (current master) |
| react-native |
0.85.x |
| Architecture |
New Architecture (Fabric), iOS |
Description
On the New Architecture iOS path, PagerView intermittently renders a permanently blank page — no content is visible even though children are mounted with valid frames, and switching pages does not recover it.
It is timing-dependent, so it reproduces inconsistently — most often when the pager is mounted as part of a screen that is still being attached (e.g. behind a navigation transition, inside a freshly-pushed screen or a tab).
Root cause
In ios/PagerViewProvider.swift, setupView() assigns self.hostingController before confirming that reactViewController() is non-nil:
private func setupView() {
if self.hostingController != nil {
return
}
self.hostingController = UIHostingController( // assigned unconditionally
rootView: PagerView(props: props, delegate: delegate),
ignoreSafeArea: true
)
if let hostingController, let parentViewController = reactViewController() {
// addChild / addSubview / pinEdges happen ONLY here
}
}
setupView() is called from didMoveToWindow(). On the first pass reactViewController() can be nil (the view is in a window but its owning view controller isn't attached yet). When that happens:
- The
if let … reactViewController() block is skipped, so the SwiftUI hosting view is never added as a subview and never pinned → its frame stays .zero → the page is blank.
self.hostingController is now non-nil, so the next didMoveToWindow() (when the VC is available) hits the if self.hostingController != nil { return } early-return and setup never retries.
Net result: a blank pager for the lifetime of the view.
Evidence (device logs)
With temporary logging in PagerViewProvider / PageChildViewController:
setupView creating hostingController ... reactVC=0 // reactViewController() was nil
didMoveToWindow hasWindow=0 ... // detached
didMoveToWindow hasWindow=1 provider.bounds={390,754} ... // re-attached, VC now exists
setupView SKIPPED (hostingController already exists) // never retries
provider.layoutSubviews bounds={390,653} hostingView.frame={0,0,0,0} // host never sized
provider.layoutSubviews bounds={390,700} hostingView.frame={0,0,0,0} // stays blank
provider.bounds is correct while hostingController.view.frame stays {0,0,0,0}.
Reproducible steps
- iOS, New Architecture enabled.
- Render a
PagerView inside a screen that is pushed/attached (so reactViewController() is nil on the first didMoveToWindow).
- The page area is blank (intermittently); switching pages does not help.
Proposed fix
Guard on reactViewController() before creating/assigning the hosting controller (so a failed pass leaves hostingController nil and can retry), and retry setupView() from layoutSubviews() so attachment happens as soon as the VC hierarchy is ready.
PR: #1088
Environment
master)Description
On the New Architecture iOS path,
PagerViewintermittently renders a permanently blank page — no content is visible even though children are mounted with valid frames, and switching pages does not recover it.It is timing-dependent, so it reproduces inconsistently — most often when the pager is mounted as part of a screen that is still being attached (e.g. behind a navigation transition, inside a freshly-pushed screen or a tab).
Root cause
In
ios/PagerViewProvider.swift,setupView()assignsself.hostingControllerbefore confirming thatreactViewController()is non-nil:setupView()is called fromdidMoveToWindow(). On the first passreactViewController()can be nil (the view is in a window but its owning view controller isn't attached yet). When that happens:if let … reactViewController()block is skipped, so the SwiftUI hosting view is never added as a subview and never pinned → its frame stays.zero→ the page is blank.self.hostingControlleris now non-nil, so the nextdidMoveToWindow()(when the VC is available) hits theif self.hostingController != nil { return }early-return and setup never retries.Net result: a blank pager for the lifetime of the view.
Evidence (device logs)
With temporary logging in
PagerViewProvider/PageChildViewController:provider.boundsis correct whilehostingController.view.framestays{0,0,0,0}.Reproducible steps
PagerViewinside a screen that is pushed/attached (soreactViewController()is nil on the firstdidMoveToWindow).Proposed fix
Guard on
reactViewController()before creating/assigning the hosting controller (so a failed pass leaveshostingControllernil and can retry), and retrysetupView()fromlayoutSubviews()so attachment happens as soon as the VC hierarchy is ready.PR: #1088