Custom TopBar button (react component) never resizes to content width under Fabric on iOS 26 and resets to 44pt after any button rebuild
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 48/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Tranquilo
- Stack tecnológico
- objective-c, react-native
- Área
- mobile
Línea de trabajo
Comienza con RCTFabricSurface.mm y compara el manejo del tamaño intrínseco con RCTSurface.mm; después, sigue la ruta del delegate a través de RNNReactButtonView.mm. Lee RNNUIBarButtonItem.mm y RNNButtonsPresenter.setButtons: para seguir la creación de constraints y la reconstrucción de los botones. Se considera terminado cuando las anchuras determinadas por el contenido funcionan en Fabric, se actualizan cuando cambia el contenido y permanecen estables después de volver a aplicar TopBar repetidamente.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
What happened?
On iOS 26 with the TopBar (RNNReactButtonView/RNNUIBarButtonItem's initWithCustomView: code path, gated behind if (@available(iOS 26.0, *))), a custom React component used as a topBar.rightButtons[].component never grows past the reserved 44pt minimum slot, even though the button is clearly designed to support it (see the kMinBarButtonSlotSize / "grow width once when React reports intrinsic size" comments in RNNUIBarButtonItem.mm and RNNReactButtonView.mm).
Tracked this down to two separate, compounding bugs in the current implementation:
-
The width-growth mechanism never fires under Fabric (New Architecture).
The whole feature depends on-surface:didChangeIntrinsicSize:being called onRNNReactButtonView's delegate. That callback is only ever invoked by the legacy, non-FabricRCTSurface(seeRCTSurface.mm,setIntrinsicSize:→[delegate surface:self didChangeIntrinsicSize:...], driven byrootShadowView:didChangeIntrinsicSize:). Under the New Architecture,RCTFabricSurfacedeclares the sameintrinsicSizeproperty (inherited fromRCTSurfaceProtocol) but never sets it and never calls the delegate method at all — there is no matching code path inRCTFabricSurface.mm. As a result,RNNReactButtonView.intrinsicSize/measuredSurfaceContentSizeis always{0,0}and the button's width constraint is never updated from its initial 44pt value, regardless of how wide the mounted React content actually is. -
Even after working around (1), the button snaps back to 44pt the next time TopBar buttons are rebuilt (e.g. reselecting a bottom tab, or any
mergeOptions/appear-triggered re-application oftopBar.rightButtons).RNNButtonsPresenter.setButtons:callsRNNButtonBuilder.build:→initWithCustomView:and constructs a brand newRNNUIBarButtonItemevery time buttons are applied, even though the underlyingRNNReactButtonView(looked up viaRNNReactComponentRegistry.createComponentIfNotExists:) is reused (it's keyed by componentId in a map and only replaced/removed when actually different).initWithCustomView:unconditionally creates newUILayoutPriorityRequiredwidth/height constraints on that reused view every single time, without ever deactivating the constraints created by the previousRNNUIBarButtonIteminstance. This leaves multiple conflicting required-priority width constraints active on the same view (e.g. one pinned at the previously-grown width, a fresh one reset to 44pt) — Auto Layout can't satisfy both, and in practice the newly-added 44pt constraint wins, visibly snapping the button back down.
What was the expected behaviour?
A custom React component used as a TopBar button should size itself to its actual rendered content width (bounded below by the ~44pt minimum tap-target size), and should keep tracking that width correctly:
- On initial mount, based on the component's real rendered content, not just the reserved 44pt placeholder.
- On subsequent content changes within the same mounted component (e.g. a counter/badge whose text gets longer or shorter).
- Consistently across repeated TopBar button re-applications (e.g. switching bottom tabs away and back), without the width getting reset or fighting with stale constraints from a previous
RNNUIBarButtonIteminstance.
Was it tested on latest react-native-navigation?
- I have tested this issue on the latest react-native-navigation release and it still reproduces.
Help us reproduce this issue!
Reproduction steps
-
Clone this public minimal reproduction repo:
https://github.com/matyi/RNNGlassRepro -
Run the app and open the screen that uses a custom React component in topBar.rightButtons.
-
Observe that the button renders variable-width content, but its width stays constrained and the content gets clipped instead of expanding to fit.
-
As a workaround, manually measure the mounted view hierarchy and pass the actual size through handleIntrinsicSizeChange:. With that fallback in place, the button grows correctly on first mount.
-
Put the screen inside a bottomTabs layout.
-
Let the button grow, then switch to another tab and back, or trigger any flow that causes topBar.rightButtons to be re-applied, such as a mergeOptions call in componentDidAppear.
-
Observe that the button width resets to the minimum size and clips the content again, even though the button content itself has not changed.
In what environment did this happen?
- React Native Navigation version:
8.8.11 - React Native version:
0.81.x(or even the lates 0.86.x) - Has Fabric (React Native's new rendering system) enabled: yes
- Node version:
v22.19.0 - Device model: reproduced on iOS 26.1 simulator, also iphone 15 ios 26.5 real device
- iOS version: 26.1, 26.5
- Lenguaje dominante
- MDX
- Estrellas
- 13.2k
- Forks
- 2.6k
- Merge medio
- 2 d 10 h
- PR fusionados (30 d)
- 6
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de wix/react-native-navigation
-
needs triage triage: documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
wix/react-native-navigation#8343 · 1 comentario ·
-
[Fix] searchBar `focus:` true ignored on mergeOptions when searchController already existsPosiblemente ocupada @IsaacIsrael la tomó hace 158 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
wix/react-native-navigation#8318 ·
-
Build Failed with RN 0.87Abiertoneeds triage type: accepted/bug
Dificultad 4/5 3-5 días Aptitud para principiantes 25/100
wix/react-native-navigation#8365 · 2 comentarios ·
-
`showOverlay` creates a scene-less `UIWindow`, so overlays never appear under UIScene lifecyclePosiblemente ocupada @yedidyak la tomó hace 3 días. Abiertoplatform: iOS type: accepted/bug
Dificultad 3/5 1-2 días Aptitud para principiantes 68/100
wix/react-native-navigation#8345 · 2 comentarios · 2 reacciones ·
-
platform: iOS type: accepted/bug
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
wix/react-native-navigation#8340 ·
Todos los issues de wix/react-native-navigation
Issues similares
-
documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
patarapolw/lingua_srs#103 ·
Los mantenedores suelen responder en 1 día
-
feat: 앱 정보에 개인정보처리방침과 고객지원 연결Posiblemente ocupada @xrpjwk8 la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
DeveloperAcademy-POSTECH/2026-C6-A13-Hear-I-am#120 ·
Los mantenedores suelen responder en 1 día
-
Bug
Dificultad 1/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 1 día
-
e2e-failure
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
home-assistant/android#7809 ·
Los mantenedores suelen responder en 1 día
-
移动端下载页实时吞吐与筛选栏滚动层级不一致Abiertoenhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Los mantenedores suelen responder en 1 día