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

React调用localhost:3001的Express API返回null的问题求助

问题描述

在React中使用useEffect和useState结合fetch获取JSON数组并渲染页面时,遇到以下问题:

  • 用json-server实现的localhost:3333/list接口可正常工作;
  • 切换到自研的Express API(localhost:3001/peeps,同样包含id和name字段,未修改渲染代码)时,Fetch报错,data值为null;
  • API终端能输出JSON日志,说明请求已到达,但React无法获取数据。

已确认信息:

  • 已给API添加Access-Control-Allow-Origin: *;
  • json-server接口有响应延迟,自研API无延迟。

已简化项目测试两天,仍未解决问题。


提供的代码

Express API控制器代码(Postman测试通过)

// Retrieve all Peeps from the database.
exports.findAll = (req, res) => {
    Peep.getAll((err, data) => {
        if (err)
            res.status(500).send({
                message:
                    err.message || "Some error occurred while retrieving peeps."
            });
        else {
        res.header("Access-Control-Allow-Origin", "*");
        res.send(data);
    }
        
    });
};

React的App.js代码

import React, { useEffect, useState } from 'react';
import './App.css';
import { getList } from './services/list';

function App() {
  const [list, setList] = useState([]);
  
  useEffect(() => {
    let mounted = true;
    getList()
      .then(items => {
        if(mounted) {
          setList(items)
        }
      })
    return () => mounted = false;
  }, [])

  alert(list);

  return(
    <div className="wrapper">
      <h1>My List</h1>
     <ul>
       {list.map(item => <li key={item.item}>{item.item}</li>)}
     </ul>
   </div>
  )
}

export default App;

排查与解决方案

1. 检查getList函数的响应处理

问题大概率出在getList的实现上,fetch需要显式调用.json()解析响应,同时要处理错误状态:

export const getList = () => {
  return fetch('http://localhost:3001/peeps')
    .then(res => {
      // 先验证响应状态
      if (!res.ok) throw new Error(`HTTP错误: ${res.status}`);
      return res.json(); // 必须调用此方法解析JSON数据
    })
    .catch(err => {
      console.error('Fetch请求失败:', err);
      throw err; // 抛出错误以便组件捕获处理
    });
};

2. 修正渲染代码的字段匹配

你的渲染代码使用item.item,但API返回的字段是id和name,字段不匹配会导致渲染失败甚至影响状态更新,需修改为:

{list.map(item => <li key={item.id}>{item.name}</li>)}

3. 全局设置CORS头

将CORS设置移到Express全局中间件,确保所有请求(包括错误响应)都带上跨域头:

const express = require('express');
const app = express();

// 全局CORS配置
app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

// 挂载路由
const peepsRouter = require('./routes/peeps');
app.use('/peeps', peepsRouter);

4. 替换调试方式并捕获错误

去掉alert(list)(会显示[object Object]且干扰调试),改用console.log查看数据,并添加错误捕获:

useEffect(() => {
  let mounted = true;
  getList()
    .then(items => {
      if(mounted) {
        console.log('获取到的数据:', items);
        setList(items);
      }
    })
    .catch(err => {
      console.error('获取列表失败:', err);
    });
  return () => mounted = false;
}, []);

5. 确认API返回的数据结构

确保Express API返回的是数组格式的JSON,而非嵌套对象(比如{data: [...]}),如果是嵌套结构,getList里需要调整为return res.json().then(data => data.data)。


内容的提问来源于stack exchange,提问作者David L. Whitehurst

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:05:55