DEV Community

Kyle Jung
Kyle Jung

Posted on

Finding Bounding Box using Mapbox GL on React Native

Recently at work, I have been using Maps SDK for React Native to implement a map feature for our app.
My task was mainly to get the bounding box to determine the pins to display on the screen since there would be performance issues if I load all the pins even outside of the viewport. I have struggled and wrapped my head around this task for a few days and I hope others have a better time figuring out this issue of the bounding box not rendering at all due to promise issues. This is also a Relevant Issue.

Maps SDK for React Native is based on Mapbox GL JS. Here is the documentation for Mapbox Maps SDK for React Native which is a community-maintained React Native library that provides reusable JS components for integrating Mapbox maps into iOS and Android apps. Since it is just maintained by volunteers and is constantly updating, some examples of the props or the functions of the existing components were not clear enough.

The function I was trying to use was getVisibleBounds() of the MapView component. getVisibleBounds() returns the coordinate bounds(ne, sw) visible in the users’s viewport.
This is the example usage in the documentation:
const visibleBounds = await this._map.getVisibleBounds();
I have rendered my MapPage as a functional component, which did not allow me to make use of this._map.

My initial attempt was to create an async function that would return the bounding box as such:

   const renderBox = async () => {
      try {
        const visibleBounds = await MapboxGl.MapView.getVisibleBounds();
      } catch(e) {
        return e
      }
        return visibleBounds
    }
Enter fullscreen mode Exit fullscreen mode

However, this function threw an error message like this: Objects are not valid as a React child (found: object with keys {_U, _V, _W, _X}). This turned out to be a promise issue, and the following is a way to get around it.

I first created a region state that has an initial state of a location like this: const [region, setRegion] = useState(location). location is an array that represents a coordinate as such [longitude, latitude].

By making use of the useEffect hook, I logged all the properties of the region in the user's viewport as such.
useEffect(() => console.log(region), [region])
The following was the log.

[Sat Jul 16 2022 15:40:42.298]  LOG      {"geometry": {"coordinates": [-87.58876641738603, 42.53691705896288], "type": "Point"}, "properties": {"animated": false, "heading": -0, "isUserInteraction": true, "pitch": 0, "visibleBounds": [[Array], [Array]], "zoomLevel": 4}, "type": "feature" }
Enter fullscreen mode Exit fullscreen mode

So I inspected the properties property of this object by logging region.properties and got the following log.

[Sat Jul 16 2022 15:40:58.570]  LOG      {"animated": false, "heading": -0, "isUserInteraction": true, "pitch": 0, "visibleBounds": [[-78.56114431259272, 51.56343338258], [-96.64150070383894, 32.005443763933826]], "zoomLevel": 4}
Enter fullscreen mode Exit fullscreen mode

Thus, by getting region.properties.visibleBounds, I was able to get the two coordinates of the user's viewport [[ne],[sw]] in every region change.

I hope this article helps others who have been running into similar issues. If there is a better fix by using the getVisibleBounds() function directly, it would also be greatly appreciated!

Top comments (0)