DEV Community

orjinameh
orjinameh

Posted on

How I Fixed a Geolocation Permission Bug in a Next.js App

While contributing to Accuguide — an open source platform that helps people discover accessible places and services — I came across an annoying bug where the browser was asking for location permission on every single page load, not just when it was actually needed.

In this article I'll walk you through what caused it, how I tracked it down, and how I fixed it.


The Problem

When you visit any page on Accuguide, the browser would immediately pop up:

"accuguide.org wants to know your location"

This happened even on pages like /info/about or /legal/privacy where location data is completely irrelevant. It was bad UX and also hurt the site's Lighthouse/PageSpeed score under the "Avoids requesting permissions on page load" audit.

The expected behavior was simple: only ask for location permission on the /search page, and only when the user has actually typed a search query.


Finding the Bug

The location logic lived in a React context called LocationProvider in app/contexts/location-context.tsx.

Inside it was this useEffect:

// ❌ The problem
useEffect(() => {
  requestLocationPermission()
}, [])
Enter fullscreen mode Exit fullscreen mode

This runs on every page because LocationProvider was wrapped around the entire app in the root layout. The empty dependency array [] means it fires once on mount — but since it's in the root layout, "mount" happens on every page.


Understanding the Fix

The fix had two parts:

Part 1: Remove the auto-trigger from LocationProvider

Remove the useEffect that was automatically requesting location on mount:

// ✅ Remove this entirely from LocationProvider
useEffect(() => {
  requestLocationPermission()
}, [])
Enter fullscreen mode Exit fullscreen mode

Now LocationProvider no longer automatically asks for location. It just provides the context — location must be requested explicitly.

Part 2: Request location only on the search page with a query

In app/search/page.tsx, add logic to request location only when:

  • The user is on the search page
  • There is an active search query
const searchParams = useSearchParams()
const query = searchParams.get('q')
const { requestLocationPermission, location } = useLocation()

useEffect(() => {
  if (query && !location) {
    requestLocationPermission()
  }
}, [query])
Enter fullscreen mode Exit fullscreen mode

Breaking this down:

  • query — the search term from the URL (?q=coffee shops)
  • !location — only request if we don't already have location
  • [query] — only re-run when the query changes

Why This Matters

Before the fix:

  • ❌ Location permission prompt appears on every page
  • ❌ Lighthouse flags "Avoids requesting permissions on page load"
  • ❌ Users get confused and deny permission unnecessarily
  • ❌ Browser may block future permission requests after repeated denials

After the fix:

  • ✅ Location permission only requested on /search page
  • ✅ Only triggered when there's an active search query
  • ✅ Lighthouse audit passes
  • ✅ Users understand WHY location is needed (they're searching!)

The Key Lesson

Context providers run on every page. If you put side effects like requestLocationPermission() inside a provider that wraps your whole app, it will run everywhere.

Always ask: "Where does this actually need to happen?" Then put the logic there — not in a global provider.

// ❌ Don't do this in a global provider
useEffect(() => {
  doSomethingThatShouldOnlyHappenInOnePlace()
}, [])

// ✅ Do this in the specific component/page that needs it
useEffect(() => {
  if (conditionIsRight) {
    doSomethingThatShouldOnlyHappenInOnePlace()
  }
}, [dependency])
Enter fullscreen mode Exit fullscreen mode

Real World Impact

This is a common mistake in React apps. I've seen it with:

  • Analytics tracking firing on pages it shouldn't
  • Cookie consent popups appearing multiple times
  • Auth checks running unnecessarily on public pages

The pattern is always the same: a side effect placed too high in the component tree.


Summary

Before After
Location prompt Every page Search page only
Trigger condition On mount When query exists
Lighthouse audit ❌ Fails ✅ Passes
User experience Confusing Intuitive

If you found this helpful, check out the Accuguide repo and my GitHub profile.

Have questions or spotted something I missed? Drop a comment below!

Top comments (0)