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

NextJS13本地Fetch返回500:如何结合Context实现数据获取?

NextJS13 App Router:本地路由数据与React Context结合的异常问题

问题详情

切换至NextJS13并使用新的App Router时,遇到Fetch返回异常问题。目录结构如下:

/app
  /context
    index.tsx
  /measurement
    route.ts

Context Provider 代码(/app/context/index.tsx)

export const MeasurementContext = createContext([]);

const fetcher = (...args) => fetch(...args);

const MeasurementProvider = ({ children }) => {
  const [elements, setElements] = useState([]);
  const [useSwr, setUseSwr] = useState(false);
  const { data, isLoading, error } = useSWR(useSwr ? "/measurement" : null, fetcher);

  useEffect(() => {
    if (!elements.length) {
      setUseSwr(true);
    }
  }, [elements]);

  useEffect(() => {
    setUseSwr(false);
    data && setElements(data);
  }, [data]);

  return <MeasurementContext.Provider value={elements}>{children}</MeasurementContext.Provider>;
};

export default MeasurementProvider;

路由处理代码(/app/measurement/route.ts)

export async function GET() {
  try {
    const data = await getMeasurements();

    if (data.length) {
      return data;
    }
  } catch (e) {
    console.error(e, "error msg");
  }
}

已知路由可返回有效数据,但Context Provider中出现500内部服务器错误。已尝试方案:

  • 使用NextResponse返回JSON格式数据
  • 尝试通用Fetch并在多组件中测试响应差异

需求:如何在NextJS13中结合本地路由数据与React Context?


解决方案

1. 修复API路由的响应格式

NextJS13 App Router要求API路由必须返回NextResponse对象,直接返回原始数据会触发500错误。修改/app/measurement/route.ts:

import { NextResponse } from 'next/server';

export async function GET() {
  try {
    const data = await getMeasurements();
    // 统一返回JSON格式响应,无论数据是否为空
    return NextResponse.json(data);
  } catch (e) {
    console.error(e, "error msg");
    // 捕获错误并返回标准错误响应
    return NextResponse.json({ error: '获取测量数据失败' }, { status: 500 });
  }
}

2. 简化Context Provider逻辑

原代码中useSwr的状态切换逻辑冗余,容易引发状态循环。同时,App Router下的客户端组件必须显式声明'use client';才能使用React Hooks。修改后的/app/context/index.tsx:

'use client';
import { createContext, useState, useEffect } from 'react';
import useSWR from 'swr';

export const MeasurementContext = createContext({
  elements: [],
  isLoading: false,
  error: null
});

// 完善fetcher函数,确保解析响应并处理错误
const fetcher = async (url: string) => {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`请求失败:${res.status}`);
  return res.json();
};

const MeasurementProvider = ({ children }) => {
  const [elements, setElements] = useState([]);
  const { data, error, isLoading } = useSWR('/measurement', fetcher);

  // 当SWR获取到数据时更新Context状态
  useEffect(() => {
    if (data) setElements(data);
  }, [data]);

  return (
    <MeasurementContext.Provider value={{ elements, isLoading, error }}>
      {children}
    </MeasurementContext.Provider>
  );
};

export default MeasurementProvider;

3. 全局挂载Context Provider

在app/layout.tsx中挂载Provider,确保所有子组件都能访问Context:

import MeasurementProvider from './context';

export default function RootLayout({ children }) {
  return (
    <html lang="zh-CN">
      <body>
        <MeasurementProvider>{children}</MeasurementProvider>
      </body>
    </html>
  );
}

4. 关键注意事项

  • 客户端组件声明:App Router中使用useState、useSWR等Hooks的组件必须添加'use client';指令,否则会在服务端渲染时出错。
  • Fetcher函数解析:原代码中直接返回fetch(...args),未解析响应为JSON,导致SWR的data是Response对象而非实际数据,需通过res.json()解析。
  • 错误处理:API路由和Fetcher函数都要添加错误捕获,避免未处理的异常导致500错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 02:33:20