React结合Laravel开发表格搜索 页面初始无数据需搜索后才显示如何解决
实现页面初始加载全量患者数据
问题说明
当前组件仅在输入框内容变化时触发接口请求,初始状态data为空数组,且后端路由要求必须传入key参数,因此页面首次加载无默认展示数据。
可选实现方案
方案1:前端本地筛选(数据量较小时优先选用,性能更优)
该方案首次加载时一次性拉取全量数据,后续搜索直接在本地内存中匹配,无需每次输入都请求后端。
前端改动
首先引入React的useEffect钩子用于触发首次加载,新增原始全量数据的存储状态,修改搜索逻辑为本地筛选:
// 补充引入useEffect import { useState, useEffect } from "react"; function SearchPatient() { // 存储表格展示数据 const [data, setData] = useState([]); // 存储全量原始数据,避免搜索后原始数据丢失 const [allPatients, setAllPatients] = useState([]); // 组件首次挂载时自动拉取全量数据 useEffect(() => { async function loadAllPatients() { const res = await fetch("http://localhost:8000/api/search/"); const resData = await res.json(); setData(resData); setAllPatients(resData); } loadAllPatients(); }, []); // 空依赖数组表示仅在组件首次加载时执行 // 本地筛选处理函数 function handleSearch(e) { const keyword = e.target.value.trim().toLowerCase(); // 输入为空时直接展示全量数据 if (!keyword) { setData(allPatients); return; } // 按姓名字段模糊匹配 const filteredData = allPatients.filter(patient => patient.nom.toLowerCase().includes(keyword) ); setData(filteredData); } return ( <div> <Container> <div className="form-group"> <label htmlFor="exampleInputEmail1">Search</label> <input type="text" className="form-control" placeholder="Search" id="nom" onChange={handleSearch} /> </div> {/* 表格部分代码保持原有逻辑不变 */} <Table className="table table-hover"> <Thead className="thead-light text-center"> <Tr> <Th>N°</Th> <Th style={{ width: "6%" }}>NOM</Th> <Th>PRÉNOM</Th> </Tr> </Thead> <Tbody className="text-center"> {data.map((patient) => ( <Tr> <Td style={{ verticalAlign: "middle" }} className="text-muted"> <b>{patient.id}</b> </Td> <Td style={{ verticalAlign: "middle" }}>{patient.nom} </Td> <Td style={{ verticalAlign: "middle" }}>{patient.prenom} </Td> </Tr> ))} </Tbody> </Table> </Container> </div> ); }
后端改动
将Laravel路由的key参数设为可选,控制器处理空参数时返回全量数据:
// 路由中给参数加? 标记为可选 Route::get('/search/{key?}/', [PatientController::class, 'search']);
public function search($key = null) { // 无传入搜索关键词时返回全部患者数据 if (!$key) { return Patient::all(); } // 有关键词时执行原有模糊查询逻辑 return Patient::where('nom','Like',"%$key%")->get(); }
方案2:保留后端实时搜索逻辑(数据量较大时选用)
如果不想改动原有搜索的后端请求逻辑,仅需在组件首次加载时主动触发一次空关键词的搜索,即可加载全量数据。
前端改动
仅需引入useEffect钩子,在组件挂载时主动调用一次search(''),原有逻辑全部保留:
// 补充引入useEffect import { useState, useEffect } from "react"; function SearchPatient() { const [data, setData] = useState([]); async function search(key) { let result = await fetch("http://localhost:8000/api/search/" + key); result = await result.json(); setData(result); } // 组件首次加载时主动触发空关键词搜索,拉取全量数据 useEffect(() => { search(''); }, []); return ( // 原有JSX代码完全不变 <div> <Container> <div className="form-group"> <label htmlFor="exampleInputEmail1">Search</label> <input type="text" className="form-control" placeholder="Search" id="nom" onChange={(e) => search(e.target.value)} /> </div> <Table className="table table-hover"> <Thead className="thead-light text-center"> <Tr> <Th>N°</Th> <Th style={{ width: "6%" }}>NOM</Th> <Th>PRÉNOM</Th> </Tr> </Thead> <Tbody className="text-center"> {data.map((patient) => ( <Tr> <Td style={{ verticalAlign: "middle" }} className="text-muted"> <b>{patient.id}</b> </Td> <Td style={{ verticalAlign: "middle" }}>{patient.nom} </Td> <Td style={{ verticalAlign: "middle" }}>{patient.prenom} </Td> </Tr> ))} </Tbody> </Table> </Container> </div> ); }
该方案的后端改动和方案1完全一致,无需额外调整。
注意事项
- 方案1 适合数据量小于1000条的场景,本地筛选无需等待后端响应,搜索体验更流畅
- 方案2 适合需要分页、复杂权限校验或数据量较大的场景,所有筛选逻辑仍由后端控制
- 调整Laravel路由时需确保可选参数的标记
?正确添加,否则会出现404错误
内容的提问来源于stack exchange,提问作者AlyaKra
相关产品推荐
相关产品推荐

