Gif of small pixel dog running back and forth along the top of the page. His name is Byte.

Connecting Local Users with Geolocation in React

I am currently working on a React app that helps content creators find and collaborate with other creators in their area. Thankfully, the Geolocation Web API makes getting a user’s coordinates simple. I will walk through how I used this API to update a user’s coordinates at login, and share a useful function I found for filtering users by distance.

First, I added the following code within the useEffect hook in App.js to prompt the user to allow location services:

if ('geolocation' in navigator) {
  console.log('geolocation supported')
} else {
  alert('no geolocation support')
}

Next, I called getCurrentPosition after the login action and dispatched the latitude and longitude to my geolocate action:

dispatch(login(email, password)).then(() => {
  navigator.geolocation.getCurrentPosition((position) => {
    dispatch(geolocate(position.coords.latitude, position.coords.longitude))
  })
})

The geolocate action looks like this:

//Update Geolocation
export const geolocate = (latitude, longitude) => async (dispatch) => {
  try {
    const body = {
      latitude,
      longitude
    }
    await api.post('/users/geolocation', body)
  } catch (err) {
    const errors = err.response.data.errors
    if (errors) {
      errors.forEach((error) => dispatch(setAlert(error.msg, 'danger')))
    }
  }
}

Here is my post route (Express.js):

// @route    POST api/users/geolocation
// @desc     update user geolocation
// @access   Public

router.post('/geolocation', [auth], async (req, res) => {
  try {
    const user = await User.findById(req.user.id).select('-password')
    user.latitude = req.body.latitude
    user.longitude = req.body.longitude
    await user.save()
    res.json({ msg: 'Location Saved' })
  } catch (error) {
    console.error(error.message)
    res.status(500).send('Server error')
  }
})

I made sure to add latitude and longitude to my user model, and voila! I had the latest location of my users.

Now, I wanted to only show profiles within 30 km of the current user. I came across this helpful function which found the distance between two coordinate pairs:

function getDistance(lat1, lon1, lat2, lon2) {
  var R = 6371 // Radius of the earth in km
  var dLat = deg2rad(lat2 - lat1) // deg2rad below
  var dLon = deg2rad(lon2 - lon1)
  var a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(deg2rad(lat1)) *
      Math.cos(deg2rad(lat2)) *
      Math.sin(dLon / 2) *
      Math.sin(dLon / 2)
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
  var d = R * c // Distance in km
  return d
}

function deg2rad(deg) {
  return deg * (Math.PI / 180)
}

One filter later, and my task was complete:

{
  profiles.filter(
    (profile) =>
      getDistance(
        latitude,
        longitude,
        profile.user.latitude,
        profile.user.longitude
      ) < 30
  ).length > 0 ? (
    profiles.map((profile) => (
      <ProfileItem key={profile._id} profile={profile} />
    ))
  ) : (
    <h4>No profiles found...</h4>
  )
}

More Posts: