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

React替换json-server为PHP接口后数据无法显示问题咨询

React待办应用接口替换后数据不展示问题修复

问题背景

学习React过程中,最初使用json-server读取本地db.json存储待办数据,访问localhost:3000/todos接口时应用运行正常,效果如下:
待办应用正常运行效果

初始db.json内容如下:

{
  "todos": [
    {
      "id": 1,
      "title": "bath",
      "done": "false"
    }
  ]
}

后续改用MySQL存储数据,通过PHP编写接口查询todos表返回JSON格式数据,PHP代码如下:

<?php
 header('Content-Type: application/json; charset=utf8');

 include("koneksi.php");

 
 $query=mysqli_query($con,"SELECT * FROM todos");

//data array
 $array=array();
 while($data=mysqli_fetch_assoc($query)) $array[]=$data; 
 
 echo json_encode($array);
?>

访问PHP接口可正常返回如下JSON内容:

[{"id":"1","title":"bath","done":"false"}]

将前端fetch请求地址从json-server接口替换为PHP接口地址后,页面待办数据无法展示,控制台无报错。前端TodoList组件代码如下:

const TodoList = ({isRefresh, setRefresh}) => {
    const [todos, setTodos] = useState([]);

      useEffect(() => {
        // memanggil API untuk mengambil data todos
         if (isRefresh) {
        fetch("http://localhost:3000/todos")
          .then((res) => {
            return res.json();
          })
          .then((data) => {
            setRefresh(false)
            // ketika Rest API sukses, simpan data dari response ke dalam state lokal
            setTodos(data);
          })
          .catch((err) => {
            setRefresh(false)
            if (err.name === "AbortError") {
              console.log("fetch aborted.");
            }
          });
       }
       
      }, [isRefresh, setRefresh]);

问题根因

该问题不是接口返回JSON结构差异导致的,核心原因有两个:

  1. 跨域(CORS)拦截:React前端服务和PHP服务运行端口不一致(比如React默认跑在3000端口,PHP服务通常跑在80/8080端口),浏览器默认拦截不同源的接口请求。而原有fetch的catch块只处理了AbortError类型的错误,跨域、网络类错误没有打印日志,所以控制台看不到报错,请求未拿到返回值自然无法渲染数据。
  2. 逻辑排查点:需要确认替换接口后,isRefresh状态的初始值和触发逻辑正常,useEffect内的请求逻辑仅在isRefresh为true时才会执行,如果初始值为false且没有触发刷新的动作,请求根本不会发送。

注:两个接口返回的数据确实存在微小差异:json-server返回的id是数字类型,PHP返回的id是字符串类型,但该差异不会导致数据完全不展示,仅会影响后续依赖id做严格相等判断的逻辑。

修复方案

按以下步骤操作即可解决问题:

  • 给PHP接口添加跨域允许头,修正charset配置,修改后的PHP代码如下:
<?php
// 配置跨域允许,*表示允许所有源,生产环境建议替换为前端实际域名,本地调试可以写http://localhost:3000
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");
// 修正charset为标准写法utf-8
header('Content-Type: application/json; charset=utf-8');

include("koneksi.php");

$query=mysqli_query($con,"SELECT * FROM todos");

$array=array();
while($data=mysqli_fetch_assoc($query)) {
  // 可选:把id转为数字类型,和json-server返回类型保持一致,避免后续严格判断出错
  $data['id'] = (int)$data['id'];
  $array[]=$data; 
}
 
echo json_encode($array);
?>
  • 补全前端fetch的错误捕获逻辑,方便后续排查问题,修改catch块代码:
.catch((err) => {
  setRefresh(false)
  if (err.name === "AbortError") {
    console.log("fetch aborted.");
  } else {
    console.error("接口请求失败:", err);
  }
});
  • 将fetch方法中的请求地址替换为PHP接口的实际访问地址,确认地址可正常访问、返回JSON内容。
  • 检查页面初始化逻辑,保证组件首次加载时isRefresh值为true,触发请求发送。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 09:46:02