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:
- 用POST请求向
http://127.0.0.1:5000/catalog/item提交一条测试数据 - 访问
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
相关产品推荐
相关产品推荐

