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

React调用PHP查询接口返回数据无法渲染到表格问题

问题根因

问题出在原生表单默认提交行为未做拦截:你给<form>标签直接配置了action指向PHP接口、method="post"属性,点击查询按钮时浏览器会直接触发原生跨页提交逻辑,跳转到action地址把接口响应当成新页面渲染——这就是原始JSON直接铺满页面的根本原因,这个过程完全绕过了React侧的fetch请求、状态更新、组件渲染流程,Data组件根本拿不到返回数据。

修复步骤
  • 拦截表单默认提交行为,移除原生提交配置
    首先删掉<form>标签上原有的action、method属性,给表单绑定onSubmit事件,在回调第一行调用e.preventDefault()阻断浏览器默认跳页逻辑。注意非查询用途的“提交”按钮要显式加type="button",否则会被默认识别为表单提交按钮,点击同样会触发跳页。
    表单核心写法参考:
    // App组件内
    const [ico, setIco] = useState('');
    const [companyName, setCompanyName] = useState('');
    
    const handleSearch = (e) => {
      // 关键:阻断原生表单跳页
      e.preventDefault();
      // 查询逻辑不需要在这里写请求,把参数传给Data组件触发刷新即可
    }
    
    return (
      <form onSubmit={handleSearch} className="container mt-4">
        <div className="mb-3">
          <label className="form-label">IČO</label>
          <input 
            type="text" 
            className="form-control"
            // 数字校验:只允许输入数字
            onInput={(e) => e.target.value = e.target.value.replace(/\D/g, '')}
            onChange={(e) => setIco(e.target.value)}
            value={ico}
            required
          />
        </div>
        <div className="mb-3">
          <label className="form-label">Název společnosti</label>
          <input 
            type="text" 
            className="form-control"
            onChange={(e) => setCompanyName(e.target.value)}
            value={companyName}
          />
        </div>
        <button type="submit" className="btn btn-primary me-2">查询</button>
        <button type="button" className="btn btn-secondary">提交</button>
    
        {/* 嵌入Data组件,传入查询参数 */}
        <Data icoFilter={ico} companyNameFilter={companyName} />
      </form>
    )
    
  • 修正Data组件的POST请求逻辑,匹配PHP后端参数接收规则
    PHP默认从$_POST中读取application/x-www-form-urlencoded格式的参数,如果你fetch时传JSON格式的请求体,后端拿不到ico参数会返回空结果或者全量数据。Data组件核心实现参考:
    import { useEffect, useState } from 'react';
    
    function Data({ icoFilter, companyNameFilter }) {
      const [records, setRecords] = useState([]);
      const [loading, setLoading] = useState(false);
    
      const loadData = async () => {
        setLoading(true);
        try {
          const res = await fetch('http://localhost/ico/vypsani.php', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
            },
            // 用URLSearchParams组装参数,PHP可直接通过$_POST读取
            body: new URLSearchParams({
              ico: icoFilter || '',
              nazev: companyNameFilter || ''
            })
          });
          // 加容错处理,避免接口返回非JSON格式时报错
          const data = await res.json();
          setRecords(Array.isArray(data) ? data : []);
        } catch (err) {
          console.error('数据查询失败:', err);
          setRecords([]);
        } finally {
          setLoading(false);
        }
      }
    
      // 首次加载、查询参数变化时自动拉取数据
      useEffect(() => {
        loadData();
      }, [icoFilter, companyNameFilter]);
    
      // 渲染Bootstrap风格表格
      return (
        <div className="mt-4">
          {loading ? <div className="text-center py-3">加载中...</div> : (
            <table className="table table-striped table-bordered">
              <thead className="table-dark">
                <tr>
                  <th>ID</th>
                  <th>IČO</th>
                  <th>Název</th>
                  <th>Město</th>
                </tr>
              </thead>
              <tbody>
                {records.length === 0 ? (
                  <tr>
                    <td colSpan="4" className="text-center text-muted">暂无匹配数据</td>
                  </tr>
                ) : records.map(item => (
                  <tr key={item.id}>
                    <td>{item.id}</td>
                    <td>{item.ico}</td>
                    <td>{item.nazev}</td>
                    <td>{item.mesto}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      )
    }
    
    export default Data;
    
  • 调整PHP接口的响应头配置
    因为React本地服务和PHP服务端口不同,会触发跨域限制,需要在PHP代码最开头加上跨域头和JSON响应头,注意输出JSON前不要打印任何其他内容(包括HTML、多余空格、echo调试信息),否则前端解析JSON会失败:
    <?php
    // 允许跨域请求,本地开发用
    header('Access-Control-Allow-Origin: *');
    header('Content-Type: application/json; charset=utf-8');
    
    // 接收参数
    $ico = isset($_POST['ico']) ? trim($_POST['ico']) : '';
    // 保留你原有的数据库连接、查询逻辑
    // $pdo = new PDO(...);
    // 组装查询结果为数组...
    
    // 直接输出JSON后终止程序
    echo json_encode($queryResult);
    exit;
    ?>
    
验证标准

改完后满足以下表现即为修复成功:

  • 点击查询按钮时浏览器地址栏不会跳转,始终停留在React应用页面
  • 浏览器开发者工具网络面板中可以看到状态为200的POST请求,响应内容为标准JSON数组
  • 数据正常渲染在Bootstrap表格内,不会出现原始JSON直接铺在页面的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:01:40