[iOS][Fabric] Changing Dynamic Type while the app is running does not re-lay out text (root not dirtied on a layout-context-only change)
Les mainteneurs répondent en général sous 2 jours
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 45/100
Piste de recherche
Start with RootShadowNode.cpp and inspect RootShadowNode::clone, then follow layoutContext into YogaLayoutableShadowNode::configureYogaTree. The issue identifies the three layout-context inputs that need to trigger layout dirtiness and explains why comparing the full context would be too broad. Reproduce the Dynamic Type change on iOS with the New Architecture, then verify existing layout tests cover the context changes and that text relays out after the change.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Description
On iOS with the New Architecture, changing the system text size (Dynamic Type) while the app is running has no visible effect on text already on screen. React Native receives the new fontSizeMultiplier, but no layout pass runs, so text keeps its launch-time size until the app is restarted. Text mounted after the change can pick up the new size, which produces mixed layouts.
Steps to reproduce
- Build a Release app with React Native 0.88.1 (New Architecture) and any
<Text>that hasallowFontScalingleft at its default. - Launch it on an iOS simulator or device.
- Without closing the app, change the text size (Settings › Display & Brightness › Text Size, or on a simulator
xcrun simctl ui <udid> content_size accessibility-extra-large). - Return to the app.
Expected: text re-lays out at the new size.
Actual: nothing changes, in either direction. Relaunching renders the new size correctly.
Root cause
-
RCTFabricSurfacehandlesUIContentSizeCategoryDidChangeNotificationby calling_updateLayoutContextwith the newfontSizeMultiplier, which reachesSurfaceHandler::constraintLayout. That commitsRootShadowNode::clone(propsParserContext, layoutConstraints, layoutContext). -
RootShadowNode::cloneonly callsdirtyLayout()when the layout constraints change:if (layoutConstraints != getConcreteProps().layoutConstraints) { newRootShadowNode->dirtyLayout(); } -
For a layout-context-only change, the root stays clean.
RootShadowNode::layoutIfNeededthen returns early (getIsLayoutClean()), solayoutTree→configureYogaTreenever runs. -
That means the existing font-scale handling in
YogaLayoutableShadowNode::configureYogaTreenever gets a chance to run, even thoughenableFontScaleChangesUpdatingLayoutdefaults totrue. That code marks measurable nodes dirty when theirfontSizeMultiplierdiffers from the new one. -
pointScaleFactorandswapLeftAndRightInRTLare consumed byconfigureYogaTreein the same way, so a change to either alone has the same problem.
The same code is on main as of 2026-11-10 (RootShadowNode.cpp last changed in 178c30d7ac). #59285 makes ParagraphShadowNode drop content built for another fontSizeMultiplier, but that only helps once a layout pass actually runs.
Proposed fix
Dirty the root when any layout-context input that configureYogaTree consumes changes:
- if (layoutConstraints != getConcreteProps().layoutConstraints) {
+ const auto& previousContext = getConcreteProps().layoutContext;
+ if (layoutConstraints != getConcreteProps().layoutConstraints ||
+ layoutContext.fontSizeMultiplier != previousContext.fontSizeMultiplier ||
+ layoutContext.pointScaleFactor != previousContext.pointScaleFactor ||
+ layoutContext.swapLeftAndRightInRTL !=
+ previousContext.swapLeftAndRightInRTL) {
newRootShadowNode->dirtyLayout();
}
The full LayoutContext == is deliberately not used: it also compares affectedNodes (a per-pass pointer) and the viewport fields, which would dirty the root on unrelated commits.
I traced this in source and reproduced the symptom in a Release build. I have not run the patched build myself, because our app uses the prebuilt React Native core.
Versions
React Native 0.88.1 (also present on 0.88-stable and main), Expo SDK 58, iOS 26.5 simulator, New Architecture, Hermes.
- Langage dominant
- C++
- Étoiles
- 127k
- Forks
- 25.5k
- Merge moyen
- 3 j 18 h
- PR mergées (30 j)
- 188
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de react/react-native
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
react/react-native#59945 ·
Les mainteneurs répondent en général sous 2 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
react/react-native#59944 ·
Les mainteneurs répondent en général sous 2 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
react/react-native#59942 ·
Les mainteneurs répondent en général sous 2 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
react/react-native#59939 ·
Les mainteneurs répondent en général sous 2 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
react/react-native#59929 · 1 commentaire ·
Les mainteneurs répondent en général sous 2 jours
Toutes les issues de react/react-native
Issues similaires
-
test(tools): two testkit cache tests fail unless GOCACHE and GOMODCACHE are in the environmentOuvertebacklog
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
EchoTools/nevr-runtime#2385 ·
Les mainteneurs répondent en général sous 1 jour
-
type:bug
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
tensorflow/tflite-micro#3995 ·
Les mainteneurs répondent en général sous 1 jour
-
CPU update 1.31xOuvertespeed-report
Difficulté 1/5 Moins d'une heure Accessibilité débutants 75/100
mw00/project-maya#961 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
-
not for AI lovers
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
OSGeo/gdal#15515 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour