Search code examples
reactjsnext.jsgeolocation

How to get geolocation from user with Next.js?


I am learning the Next.js. I want to get the latitude and longitude from user. And then call the API. My code is like that:

import Navbar from "../../comps/Navbar";
import Link from "next/link";
import Head from "next/head";
import styles from '../../styles/Mensen.module.css'
import { useEffect } from "react";
import { useState } from "react";
import Location from "../../comps/Location";
import navigator from "react";

export const getStaticProps = async (context) => {    
    const res = await fetch('https://openmensa.org/api/v2/canteens?near[lat]=' + lat+ '&near[lng]=' + long + '&near[dist]=50000');
    const data = await res.json();

    return {
      props: { mensen: data }
    }
}

const Mensen = ({mensen}) => {    
    return ( 
        <>
        <Head>
            <title>HTW Mensa | Mensen</title>
            <meta name="keywords" content="mensa"/>
        </Head>
        <Location />
        <div>
            <h1>Alle Mensen</h1>
            <p>Alle Mensen</p>
            {mensen.map(mensa => ( 
                <Link href={'/mensen/' + mensa.id} key={mensa.id}>
                    <a className={styles.single}> 
                        <h3>{ mensa.name }</h3>
                    </a>
                </Link>))}
        </div>
        </>
    );
}
 
export default Mensen;

The API uses latitude and longitude from user to give the places nearby. I saw that someone recommend using useEffect. But I'm not sure about that.

Could someone help me?


Solution

  • Since getStaticProps runs on the server at build time, it can't access user-specific information like geolocation. You'll have to move the logic to the client-side instead.


    Here's an example of how to retrieve the user's geolocation using the Geolocation API built-in in browsers (note that the user is notified and asked to grant permission for the API to work).

    import { useEffect, useState } from 'react'
    import Link from 'next/link';
    
    const Mensen = () => {
        const [mensen, setMensen] = useState([]);
        const [location, setLocation] = useState();
    
        const fetchApiData = async ({ latitude, longitude }) => {
            const res = await fetch(`https://openmensa.org/api/v2/canteens?near[lat]=${latitude}&near[lng]=${longitude}&near[dist]=50000`);
            const data = await res.json();
            setMensen(data);
        };
    
        useEffect(() => {
            if('geolocation' in navigator) {
                // Retrieve latitude & longitude coordinates from `navigator.geolocation` Web API
                navigator.geolocation.getCurrentPosition(({ coords }) => {
                    const { latitude, longitude } = coords;
                    setLocation({ latitude, longitude });
                })
            }
        }, []);
    
        useEffect(() => {
            // Fetch data from API if `location` object is set
            if (location) {
                fetchApiData(location);
            }
        }, [location]);
        
        return ( 
            <div>
                <h1>Alle Mensen</h1>
                <p>Alle Mensen</p>
                {mensen?.length > 0 && mensen.map(mensa => ( 
                    <Link href={`/mensen/${mensa.id}`} key={mensa.id}>
                        <a className={styles.single}> 
                            <h3>{mensa.name}</h3>
                        </a>
                    </Link>
                ))}
            </div>
        );
    };
    

    The component checks for the existence of navigator.geolocation, then tries to retrieve the current position of the user with navigator.geolocation.getCurrentPosition(). When successful, the location state variable is set which triggers the request to the openmensa.org API. Once the data is successfully fetched, the mensen state variable is set which renders the results on the page.