react-nativemapview

Display Text over MapView without Redrawing MapView when Overlayed Text Changes


I have a <MapView /> next to some position: absolute Views with Text in them. In the MapView, I have a <Circle /> within it to mark an area within the map. I have information like the user's coordinates on the overlaid text, as well as if the user is within the radius of the circle area on the map.

I want to be able to change the text being overlaid on top of the MapView without forcing a redraw of the map. Whenever the text changes, the map redraws itself, which resets the user's zoom and makes it disappear momentarily.

The text/view components are not within each other and are side by side for hierarchy.

The Location of the player is drawn on the MapView component with showUserLocation={true}. The actual coordinates are given to the Text components to display to the user with a Location.watchPositionAsync()

const myComponent = () => {
  const [location, setLocation] = useState(null);
  const [circle, setCircle] = useState({
    radius: 5,
    latitude: 0,
    longitude: 0,
  });

  // subscription to the users location
  useEffect(() => {
    subscription = await Location.watchPositionAsync(
      callback: (newLocation) => {
        setLocation(newLocation)
      }
    )
  }

  const isInCircleRadius() => {
    // return true/false based on if user is within the radius of the MapView Circle
  }

  return (
    <>
      <MapView 
        style={{ /* fullscreen all that stuff */ }}
        showUserLocation={true}>
          <Circle radius={circle.radius} center={circle.latitude, circle.longitude} />
      </MapView>
      <View>
        // Text changing here causes the MapView to redraw as well, even though this is just 
        // position: absolute and beside the MapView component
        <Text>{location.latitude} {location.longitude} {isInCircleRadius(location)}
      </View>
    </>
  )

}

I tried making the MapView into its own component and calling it within a parent component to hold the text and map component.

I tried making a local Location variable, so only the Text component reads TextSpecificLocation and the MapView can use MapSpecificLocation even though they have the exact same data. Just to make it so they don't rely on the same variable.


Solution

  • The solution was to memoize the MapView into a component and make the dependency array only what changes on the map (the circle area). And then memoize the entire screen surrounding the text and the map with a dependency array of the mutable variables there.

    Very stringy problem for anyone to gather enough context on here, so thank you for your efforts.

    const MapComponent = useMemo(() => {
      return (
        <MapView>
          <Circle radius={circleInfo.radius} latitude={...} longitude={...} />
        </MapView>
    }, [circleInfo]);
    
    const MainScreen = useMemo(() => {
      return (
        <View>
          <MapComponent />
          <OverLayedText tellPlayerIfSafe={isSafe} />
        </view>
      );
    }, [MapComponent, isSafe, location]);
    
    return (<> {MainScreen} </>);