You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中获取用户地理位置并调用OpenMensa API?

问题分析与解决方案

你的代码存在几个核心问题:

  • getStaticProps 是Next.js的静态生成方法,在构建阶段运行在服务器端,根本拿不到客户端用户的地理位置,而且代码里的lat和long变量未定义,直接使用会报错。
  • 错误导入了navigator,它是浏览器的全局对象,不需要从react导入。

要实现获取用户位置再调用API的需求,必须在**客户端组件里用useEffect+useState**完成,因为地理位置只能在浏览器环境中获取。


修改后的完整代码

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

const Mensen = () => {    
    // 定义状态:存储经纬度、食堂数据、加载状态、错误信息
    const [latitude, setLatitude] = useState(null);
    const [longitude, setLongitude] = useState(null);
    const [mensen, setMensen] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        // 检查浏览器是否支持地理位置API
        if (!navigator.geolocation) {
            setError("你的浏览器不支持地理位置服务");
            setLoading(false);
            return;
        }

        // 获取用户当前位置
        navigator.geolocation.getCurrentPosition(
            (position) => {
                // 成功获取位置,更新经纬度
                const lat = position.coords.latitude;
                const lng = position.coords.longitude;
                setLatitude(lat);
                setLongitude(lng);

                // 调用OpenMensa API获取附近食堂
                fetch(`https://openmensa.org/api/v2/canteens?near[lat]=${lat}&near[lng]=${lng}&near[dist]=50000`)
                    .then(res => {
                        if (!res.ok) throw new Error("API请求失败");
                        return res.json();
                    })
                    .then(data => {
                        setMensen(data);
                        setLoading(false);
                    })
                    .catch(err => {
                        setError(err.message);
                        setLoading(false);
                    });
            },
            (err) => {
                // 获取位置失败,处理错误
                setError(`获取位置失败:${err.message}`);
                setLoading(false);
            }
        );
    }, []); // 空依赖数组,确保这个useEffect只在组件挂载时运行一次

    // 渲染不同状态的内容
    if (loading) return <div>加载中...</div>;
    if (error) return <div>错误:{error}</div>;

    return ( 
        <>
        <Head>
            <title>HTW Mensa | Mensen</title>
            <meta name="keywords" content="mensa"/>
        </Head>
        <Location />
        <div>
            <h1>Alle Mensen</h1>
            <p>Alle Mensen</p>
            {mensen.length === 0 ? (
                <p>未找到附近的食堂</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;

关键说明

  • 地理位置获取:通过浏览器的navigator.geolocation.getCurrentPosition方法获取用户位置,需要用户授权浏览器访问位置信息。
  • API调用时机:在获取到经纬度后才调用API,确保请求参数正确。
  • 状态管理:用loading和error状态提升用户体验,避免页面空白或报错无提示。
  • 移除getStaticProps:因为静态生成无法处理依赖用户动态位置的请求,改用客户端数据获取。

内容的提问来源于stack exchange,提问作者Ok Oshiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 16:46:37