React应用中GET请求无法获取自定义Express API数据的原因?
React前端无法访问Cyclic.sh部署的Express API
问题背景
我正在开发一个MERN Web应用:
- Node.js服务器部署在Cyclic.sh上,通过Express API从MongoDB获取数据,浏览器直接访问API能得到预期响应:
[{"_id":"6436561b7adc14205dd193ce","title":"Sons Of Anarchy","body":"Body text goes here...","__v":0},{"_id":"6436561b7adc14205dd193cf","title":"Games of Thrones","body":"Body text goes here...","__v":0}] - Netlify上部署的React前端,请求该自定义API时无任何响应,但替换为公开API(如
https://opentdb.com/api.php?amount=1&type=multiple)就能正常工作。尝试使用no-cors模式也无法解决问题。
相关代码
Express服务器index.js
require('dotenv').config(); const express = require('express') const mongoose = require('mongoose') const Book = require("./models/books"); const app = express() const PORT = process.env.PORT || 3000 mongoose.set('strictQuery', false); const connectDB = async () => { try { const conn = await mongoose.connect(process.env.MONGO_URI); console.log(`MongoDB Connected: ${conn.connection.host}`); } catch (error) { console.log(error); process.exit(1); } } //Routes go here app.get('/', (req,res) => { res.send({ title: 'Books' }); }) app.get('/books', async (req,res)=> { const book = await Book.find(); if (book) { res.json(book) } else { res.send("Something went wrong."); } }); app.get('/add-note', async (req,res) => { try { await Book.insertMany([ { title: "Sons Of Anarchy", body: "Body text goes here...", }, { title: "Games of Thrones", body: "Body text goes here...", } ]); res.json({"Data":"Added"}) } catch (error) { console.log("err", + error); } }) //Connect to the database before listening connectDB().then(() => { app.listen(PORT, () => { console.log("listening for requests"); }) })
models/books.js
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const BookSchema = new Schema({ title: { type: String, required: true, }, body: { type: String, required: true, } }); module.exports = mongoose.model('Book', BookSchema);
React前端App.js
import React, { useState, useEffect } from "react"; import axios from "axios"; import './App.css'; function App() { const [question, setQuestion] = useState(""); const fetchQuestion = () => { setQuestion(""); axios .get('https://[expressApiUrlCyclic]/books') .then((response) => { let returnQuestion = response; setQuestion(returnQuestion); } ) } useEffect(() => { fetchQuestion(); }, []); return ( <div className="App"> <header className="App-header"> <h1>hello</h1> <h1>{JSON.stringify(question)}</h1> </header> <p>text</p> </div> ); } export default App;
原因分析
核心问题是CORS跨域限制:
- 浏览器直接访问API属于地址栏发起的简单请求,不受同源策略限制;
- React前端是从Netlify域名发起的AJAX请求,属于跨域请求,而你的Express服务器没有配置CORS响应头,浏览器会拦截服务器返回的响应;
- 使用
no-cors模式时,浏览器会禁止读取响应内容,因此依然无法获取数据。
解决方案
1. 为Express服务器配置CORS中间件
这是最直接的解决方法:
- 首先安装
cors包:npm install cors - 在Express的
index.js中引入并使用该中间件(要放在路由定义之前):const cors = require('cors'); // 允许所有域名跨域请求 app.use(cors());
可选:限制特定域名访问(更安全)
如果只希望你的Netlify前端能访问API,可以配置指定origin:
app.use(cors({ origin: 'https://your-netlify-frontend-domain.netlify.app' // 替换为你的前端实际域名 }));
2. 修复React前端代码的小问题
当前代码中,你把整个axios响应对象存入了状态,但实际需要的是响应体response.data,同时建议添加错误捕获以便排查问题:
const fetchQuestion = () => { setQuestion(""); axios .get('https://[expressApiUrlCyclic]/books') .then((response) => { setQuestion(response.data); // 仅存储响应数据 }) .catch(err => { console.error('API请求失败:', err); // 捕获并打印错误 }) }
内容的提问来源于stack exchange,提问作者Adrooid
相关产品推荐
相关产品推荐

