[Bug]: PointAnnotation Throwing an Error with Nested Children on RN 0.76 with New Architecture
Mapbox Implementation
Mapbox
Mapbox Version
default
React Native Version
0.76
Platform
iOS, Android
@rnmapbox/maps version
10.1.33
Standalone component to reproduce
import React from 'react';
import Mapbox from '@rnmapbox/maps';
import { StyleSheet, Text, View } from 'react-native';
const ANNOTATION_SIZE = 50;
const defaultCamera = {
centerCoordinate: [-73.98004319979121, 40.75272669831773],
zoomLevel: 17,
};
const corners = [
{
coordinate: [-73.980313714175, 40.75279456928388],
anchor: { x: 0, y: 1 },
},
{
coordinate: [-73.9803415496257, 40.75275624885313],
anchor: { x: 0, y: 0 },
},
{
coordinate: [-73.98048535932631, 40.752816154647235],
anchor: { x: 1, y: 0 },
},
{
coordinate: [-73.98045541426053, 40.75285444197175],
anchor: { x: 1, y: 1 },
},
];
const sides = [
{
coordinate: [-73.97952569308393, 40.75274356459241],
anchor: { x: 1 / 3, y: 0 },
},
{
coordinate: [-73.98082017858928, 40.75329086324669],
anchor: { x: 1 / 3, y: 1 },
},
{
coordinate: [-73.97985980165191, 40.752286242917535],
anchor: { x: 0, y: 1 / 3 },
containerStyle: { flexDirection: 'row' },
},
];
const styles = {
small: {
backgroundColor: 'blue',
height: ANNOTATION_SIZE,
justifyContent: 'center',
width: ANNOTATION_SIZE,
flex: 1,
},
large: {
borderColor: 'blue',
backgroundColor: 'transparent',
borderWidth: StyleSheet.hairlineWidth,
height: ANNOTATION_SIZE * 2,
justifyContent: 'center',
width: ANNOTATION_SIZE * 2,
flex: 1,
},
text: {
position: 'absolute',
fontSize: 10,
},
matchParent: {
flex: 1,
},
};
const PointAnnotationAnchors = (props) => {
return (
<Mapbox.MapView style={styles.matchParent}>
<Mapbox.Camera defaultSettings={defaultCamera} />
{corners.map((p, i) => (
<Mapbox.PointAnnotation
key={`square-${i}`}
id={`square-${i}`}
coordinate={p.coordinate}
anchor={p.anchor}
>
<View style={styles.small}>
<Text style={[styles.text, { color: 'white' }]}>
x={p.anchor.x.toPrecision(2)}, y={p.anchor.y.toPrecision(2)}
</Text>
</View>
</Mapbox.PointAnnotation>
))}
{sides.map((p, i) => {
let { x, y } = p.anchor;
if (x === 1) {
x = 0;
}
if (y === 1) {
y = 0;
}
return (
<Mapbox.PointAnnotation
key={`triangle-${i}`}
id={`triangle-${i}`}
coordinate={p.coordinate}
anchor={p.anchor}
>
<View style={[styles.large, p.containerStyle]}>
<View
style={{
height: ANNOTATION_SIZE * 2,
width: ANNOTATION_SIZE * 2 * x,
backgroundColor: 'green',
}}
/>
<View
style={{
height: ANNOTATION_SIZE * 2 * y,
width: ANNOTATION_SIZE * 2,
backgroundColor: 'green',
}}
/>
<Text style={[styles.text, { color: 'black' }]}>
x={p.anchor.x.toPrecision(2)}, y={p.anchor.y.toPrecision(2)}
</Text>
</View>
</Mapbox.PointAnnotation>
);
})}
</Mapbox.MapView>
);
};
export default PointAnnotationAnchors;
/* end-example-doc */
/** @type ExampleWithMetadata['metadata'] */
const metadata = {
title: 'Point Annotation Anchors',
tags: ['PointAnnotation'],
docs: `
Point annotation anchors test
`,
};
PointAnnotationAnchors.metadata = metadata;
Observed behavior and steps to reproduce
With RN 0.76 and the New Architecture, PointAnnotations with nested children (like a View with a Text component inside it) through an error of:
Mapbox [error] PointAnnotation supports max 1 subview other than a callout,
and don't render completely. On iOS, this results in the View being rendered, but not the Text inside the view. This can be seen in the Point Annotation Anchors example:
Expected behavior
PointAnnotations structured like this would load the View and the Text component inside it.
Notes / preliminary analysis
The parent view and its children are getting flattened, and _createViewSnapshot is being called with with the first subview in reactSubviews which on iOS ends up being the parent view if you pass something like:
<View style={styles.small}>
<Text style={[styles.text, { color: 'white' }]}>
x={p.anchor.x.toPrecision(2)}, y={p.anchor.y.toPrecision(2)}
</Text>
</View>
to PointAnnotation
Additional links and references
No response
I have the same problem
<PointAnnotation
key={square-${i}}
id={square-${i}}
coordinate={p.coordinate}
anchor={p.anchor}
{/* collapsable={false} off view flattening */}
<View style={styles.small} collapsable={false}>
<Text style={[styles.text, { color: 'white' }]}>
x={p.anchor.x.toPrecision(2)}, y={p.anchor.y.toPrecision(2)}
</Text>
</View>
Hello, we have the same issue!
@thomasgrivet you can add collapsable={false} to a component to disable flattening.
@matiastang, good callout, it looks like there were changes around this prop in RN-0.76. I'll test this out on my project to see if it fixes my issue, and report back. Thanks!
Confirmed, setting collapsable={false} on the view inside of PointAnnotation fixed my issue. Thanks @matiastang
I think it's still a valid issue we either need to fix this or at least document it.
I think it's still a valid issue we either need to fix this or at least document it.
@mfazekas, yeah documenting it would be a good idea, since the issue is stemming from a change in how RN handles optimizing the view hierarchy in 0.76. I can try to get a PR up for this later