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

Next.js 13 App目录中Fetch API路由URL解析错误求助

Next.js 13 App Router API路由与数据获取错误排查

核心错误点分析

1. API路由路径错误

你的API路由文件/src/app/location/route.ts对应的访问路径是/location,而非/api/location。App Router中,route.ts直接作为所在文件夹的路由端点,不需要额外的api前缀(除非你专门创建/app/api/location/route.ts)。这是导致URL解析失败的直接原因。

2. 服务器端调用客户端专属API

getUserLocation依赖浏览器的navigator.geolocationAPI,这是仅能在客户端运行的API,无法在服务器端的route.ts中调用。服务器端环境没有浏览器的navigator对象,执行时会直接报错。

3. RootLayout的错误返回逻辑

Layout组件必须返回合法的JSX结构,你在try块中直接return responseData会导致组件返回非JSX值,完全破坏页面渲染逻辑。

修复方案

方案1:直接在客户端组件获取地理位置(推荐)

地理位置属于客户端专属数据,无需通过服务器端API中转,直接在客户端组件中处理即可:

  1. 将useLocation.ts改为符合React习惯的自定义Hook:
// /src/app/hooks/useLocation.ts
import { useState, useEffect } from 'react';

type LocationData = { latitude: number; longitude: number };

export const useUserLocation = () => {
  const [location, setLocation] = useState<LocationData | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!("geolocation" in navigator)) {
      setError("当前设备不支持地理位置获取");
      return;
    }

    navigator.geolocation.getCurrentPosition(
      ({ coords }) => {
        setLocation({ latitude: coords.latitude, longitude: coords.longitude });
      },
      (err) => {
        setError(err.message || "获取地理位置失败");
      }
    );
  }, []);

  return { location, error };
};
  1. 在客户端页面组件中使用该Hook:
// /src/app/page.tsx
'use client';
import { useUserLocation } from '@/app/hooks/useLocation';

export default function Home() {
  const { location, error } = useUserLocation();

  return (
    <div className="location-container">
      {location ? (
        <p>你的位置:{location.latitude.toFixed(4)}, {location.longitude.toFixed(4)}</p>
      ) : error ? (
        <p className="error-text">错误:{error}</p>
      ) : (
        <p>正在获取位置...</p>
      )}
    </div>
  );
}
  1. 恢复RootLayout的正确结构(移除服务器端fetch逻辑):
// /src/app/layout.tsx
import './globals.scss';

interface LayoutProps {
  children: React.ReactNode;
}

export default function RootLayout({ children }: LayoutProps) {
  return (
    <html lang="en">
      <body>
        <main className="flex min-h-screen flex-col items-center justify-between p-24 main">
          {children}
        </main>
      </body>
    </html>
  );
}

方案2:若必须通过服务器端API中转(仅适用于需服务器处理位置数据的场景)

如果需要对位置数据做服务器端处理(如存储、调用第三方API),需由客户端先获取位置,再传递给服务器:

  1. 修改API路由为接收客户端POST请求:
// /src/app/location/route.ts
import { NextResponse } from "next/server";

export async function POST(request: Request) {
  try {
    const location = await request.json();
    // 在这里添加服务器端逻辑(如存储到数据库、调用地图API等)
    return NextResponse.json({ success: true, processedLocation: location });
  } catch (err) {
    return NextResponse.json({ success: false, error: "处理位置数据失败" }, { status: 500 });
  }
}
  1. 在客户端组件中获取位置并调用API:
// /src/app/page.tsx
'use client';
import { useState, useEffect } from 'react';

type LocationData = { latitude: number; longitude: number };

export default function Home() {
  const [location, setLocation] = useState<LocationData | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [serverResponse, setServerResponse] = useState<any>(null);

  useEffect(() => {
    const fetchAndSendLocation = async () => {
      if (!("geolocation" in navigator)) {
        setError("当前设备不支持地理位置获取");
        return;
      }

      navigator.geolocation.getCurrentPosition(
        async ({ coords }) => {
          const userLocation = { latitude: coords.latitude, longitude: coords.longitude };
          setLocation(userLocation);

          // 调用服务器端API
          const response = await fetch('/location', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(userLocation)
          });

          if (!response.ok) throw new Error("请求服务器失败");
          const data = await response.json();
          setServerResponse(data);
        },
        (err) => {
          setError(err.message || "获取地理位置失败");
        }
      );
    };

    fetchAndSendLocation();
  }, []);

  return (
    <div>
      {/* 位置渲染逻辑同方案1 */}
      {serverResponse && (
        <p>服务器处理结果:{JSON.stringify(serverResponse)}</p>
      )}
    </div>
  );
}

内容的提问来源于stack exchange,提问作者one-hand-octopus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:42:47