Connecting Local Users with Geolocation in React

Harry Herskowitz
2 min readSep 19, 2020

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 the 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>
)}

Originally published at https://harryherskowitz.com on September 19, 2020.

--

--

Harry Herskowitz
0 Followers

Harry is a web developer and videographer with a focus on using technology to empower local artists and communities