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
相关产品推荐
相关产品推荐

