-
Notifications
You must be signed in to change notification settings - Fork 185
Open
Labels
bug: react-nativeA bug that originates in React NativeA bug that originates in React Native
Description
Describe the feature request
This is a follow-up to #318 regarding the nativeProps feature request, in which @necolas raised a specific issue related to view flattening and the collapsable prop.
Brief Summary
- By default, React Native performs view flattening on both iOS and Android. This process removes "layout-only" views from the platform view tree to reduce the number of platform views created. In contrast, the web does not have a corresponding technique, as the DOM element tree is preserved as rendered.
- Layout-only views are views that handle layout-related properties like margins, padding, etc., which can be managed by Yoga and safely removed. However, views with properties like background color, opacity, borders, shadows, etc., cannot be flattened because these properties cannot be replaced by pure Yoga layout adjustments.
- View flattening distorts the platform view tree, both statically (by making views that were previously separate into siblings) and dynamically (when a view, along with all its children, transitions between being "layout-only" and an actual view).
Example of issues caused by view flattening
- Screen reader focus order: On iOS, the screen reader considers platform view grouping, reading text elements under the same parent view consecutively. With view flattening, views from different flattened containers can end up in the same container, resulting in an incorrect screen reader order (this is the issue I am currently facing).
- Validation error styling: For example, setting a red border or background around a view containing a text input to signal a validation error can cause the container view to change from "layout-only" to an actual view. This, in turn, can trigger the platform text input component to be recreated, resetting its intrinsic native state (e.g., cursor position). More details here.
- Community libraries: Libraries like React Native Gesture Handler sometimes need to attach to an actual native view. With view flattening, the required view might be removed, causing errors.
These are just a few examples of how view flattening can lead to unexpected and hard-to-diagnose issues, as it’s not always obvious which views are being removed.
Traditionally, the standard way to disable view flattening is by using the collapsable prop, which explicitly clarifies the developer's intent. However, this prop is not accessible in RSD. The proposal for nativeProps was intended to create an escape hatch to allow access to this or other similar props.
Potential solutions
- Disable view flattening in RSD altogether: This would align React Native's behavior with the DOM, where platform views are never flattened. However, this is a crude solution that would eliminate a generally useful optimization technique and could have performance implications.
- Encourage users to use React Native's
Viewinstead ofh.div, etc.: While possible, this approach requires users to maintain two sets of styles, RSD styles and React Native styles, which is a significant inconvenience. - Use another prop that disables view flattening as a side effect: For example, the
nativeIDprop (which RSD maps fromid) could be used. However, this approach lacks clarity of intent, and a future developer (or even our future selves) might mistakenly remove it, thinking the ID is unused.
Metadata
Metadata
Assignees
Labels
bug: react-nativeA bug that originates in React NativeA bug that originates in React Native