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

NextJS组件无法从Flask服务器取数据,控制台报错求助

问题:NextJS无法从Flask API获取数据,刷新后无内容+路由相关错误
  • NextJS组件可正常从模拟API(如jsonplaceholder)拉取数据,但调用本地Flask API后,刷新页面无任何内容显示
  • 控制台抛出错误:
Uncaught Error: invariant expected app router to be mounted
    at useRouter (navigation.js:126:15)
    at HotReload (hot-reloader-client.js:367:46)
    at renderWithHooks (react-dom.development.js:9745:28)
    at mountIndeterminateComponent (react-dom.development.js:14632:25)
    at beginWork$1 (react-dom.development.js:15936:32)
    at beginWork (react-dom.development.js:22789:28)
    at performUnitOfWork (react-dom.development.js:21852:24)
    at workLoopSync (react-dom.development.js:21617:17)
    at renderRootSync (react-dom.development.js:21584:21)
    at recoverFromConcurrentError (react-dom.development.js:20917:30)
    at performConcurrentWorkOnRoot (react-dom.development.js:20871:46)
    at workLoop (scheduler.development.js:200:48)
    at flushWork (scheduler.development.js:178:28)
    at MessagePort.performWorkUntilDeadline (scheduler.development.js:416:35)

NextJS组件代码

Catalog.jsx

import CatalogList from "./CatalogList";

export default function Catalog(){
    return(
        <main>
            <h2>Catalog</h2>
            <CatalogList/>
        </main>
    )
}

CatalogList.jsx

async function getItems(){
    const res = await fetch('http://127.0.0.1:5000/catalog')
    return res.json()
}

export default async function CatalogList(){
    const data = await getItems()
    const items = data.items
    return(
       <>
        <h3>should work</h3>
        {items.map((item) => (
            <div key={item.id}>
                <h3>{item.id}</h3>
            </div>
        ))}
       </>
    )
}

Flask服务器代码

from flask import Flask, jsonify, request, session
from datetime import timedelta
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
app.secret_key = "SSMIF"
app.permanent_session_lifetime = timedelta(days=10)


@app.route("/heartbeat")
def heartbeat():
    return jsonify({"status": "healthy"})


@app.route("/catalog/item", methods=["POST"])
def add_item():
    session.permanent=True
    data = request.get_json()
    id = data["id"]
    name = data['name']
    price = data['price']
    quantity = data['quantity']
    link = data['link']
    session[id] = {"id": id,"name": name, "price": price, "quantity": quantity, "link": link}
    return jsonify({'result': 'success!','id': id ,'name': name, 'price': price, 'quantity': quantity, "link": link})

@app.route("/catalog/item", methods=["PUT"])
def update_item():
    data = request.get_json()
    id = data["id"]
    if id == None:
        return jsonify({'result': 'Item does not exist. Send a POST request instead.'})
    if id in session:
        item = session[id]
        name = item.get("name","")
        price = item.get("price", "")
        quantity = item.get("quantity","")
        link = item.get("link","")
        if 'name' in data:
            name = data["name"]
        if 'price' in data:
            price = data["price"]
        if 'quantity' in data:
            quantity = data["quantity"]
        if 'link' in data:
            link = data["link"]
        session[id] = {"id": id,"name": name, "price": price, "quantity": quantity, "link": link}
        return jsonify({'result': 'success!','id': id ,'name': name, 'price': price, 'quantity': quantity, "link": link})
    else:
        return jsonify({'result': 'Item does not exist. Send a POST request instead.'})


@app.route("/catalog/item/<item_id>", methods=["DELETE"])
def remove_item(item_id):
    session.pop(item_id, None)
    return jsonify({"result":'success!'})


@app.route("/catalog", methods=["GET"])
def get_items():
    return_items = []
    for key, items in session.items():
        if is_string(key) and isinstance(item, dict): 
            return_items.append(items)
    return jsonify({"items": return_items})


if __name__ == '__main__':
    app.run()

问题排查与解决方案

1. 先修复Flask API的代码bug

你的/catalog路由有两个致命错误:

  • 循环变量名不匹配:for key, items in session.items()中定义的是items,但后面判断用的是item,会触发NameError
  • is_string函数未导入,Flask中判断字符串应该用isinstance(key, str)

修正后的/catalog路由代码:

@app.route("/catalog", methods=["GET"])
def get_items():
    return_items = []
    for key, item in session.items():
        if isinstance(key, str) and isinstance(item, dict): 
            return_items.append(item)
    return jsonify({"items": return_items})

修复后先单独测试Flask API:

  1. 用POST请求向http://127.0.0.1:5000/catalog/item提交一条测试数据
  2. 访问http://127.0.0.1:5000/catalog,确认能返回格式正确的JSON数据

2. 解决NextJS的路由环境报错

报错expected app router to be mounted通常是App Router与组件写法不兼容导致的,按以下方式调整:

方案:将CatalogList标记为客户端组件

在CatalogList.jsx顶部添加'use client'指令,同时增加错误处理避免静默崩溃:

'use client';

async function getItems(){
    const res = await fetch('http://127.0.0.1:5000/catalog')
    if (!res.ok) {
        throw new Error(`请求失败:${res.status}`);
    }
    return res.json()
}

export default async function CatalogList(){
    try {
        const data = await getItems()
        const items = data.items || []; // 兜底避免undefined
        return(
           <>
            <h3>should work</h3>
            {items.map((item) => (
                <div key={item.id}>
                    <h3>{item.id}</h3>
                </div>
            ))}
           </>
        )
    } catch (error) {
        return <div>加载失败:{error.message}</div>;
    }
}

如果使用的是Page Router(组件在pages/目录下),尝试重启NextJS开发服务器,热重载异常也可能触发该报错。

3. 验证CORS与请求连通性

  • 确认Flask服务器运行在127.0.0.1:5000,NextJS运行在默认的localhost:3000
  • 打开浏览器DevTools的Network标签,查看/catalog请求的状态码:
    • 4xx/5xx:回到Flask端排查接口逻辑
    • CORS错误:修改Flask的CORS配置为CORS(app, origins=["http://localhost:3000"])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 17:05:00