React后端驱动表格搜索/筛选功能实现问题求助
解决React + GraphQL搜索/筛选功能问题
问题背景
作为React新手,尝试在项目中实现搜索/筛选功能,使用两个GraphQL API:GET_ALL_USERS获取所有用户作为表格默认内容,SEARCH_USERS根据输入的用户名或名称匹配后端用户。但实际效果不符合预期。
期望效果
- 输入内容后点击搜索按钮,表格渲染搜索结果
- 搜索无结果时,显示「未找到包含[输入内容]的用户」
- 点击清空按钮后,表格恢复显示所有用户
- 数据库中无用户时,显示「未找到用户」
当前问题
- 输入内容时未点击搜索按钮就实时触发搜索
- 搜索无结果时表格仍显示所有用户,未显示对应提示
原代码
import { useQuery } from "@apollo/client"; import { GET_ALL_USERS, SEARCH_USERS } from "../graphql/Queries"; import { useState } from 'react'; const UsersTable = () => { const [search, setSearch] = useState('') const{ data, error, loading } = useQuery(GET_ALL_USERS) const{ data: searchedData, error: searchedError, loading:searchedLoading } = useQuery(SEARCH_USERS, { variables: { name: search || null } }) const searchedResult = searchedData ? searchedData.searchedUsers : [] const masterData =(searchedResult && searchedResult.length > 0) ? searchedResult : data?.allUsers const handleSubmit = (e: any)=>{ } return( <div> {/* search */} <div> <input type="text" placeholder='Search for user' onChange={e => setSearch(e.target.value)}/> <button onSubmit={handleSubmit}>Search</button> </div> {/*table*/} <table className="w-full text-left"> <thead> <tr> <th> Name </th> <th> Username </th> <th> Age </th> </tr> </thead> <tbody> {masterData && masterData.map((user: any)=>{ return ( <tr key={user.id}> <th> {user.name} </th> <td> {user.username} </td> <td> {user.age} </td> </tr> ) })} </tbody> </table> </div> ) }
解决方案
关键修改点
控制搜索触发时机
- 新增
searchQuery状态,仅在点击搜索按钮时赋值,作为SEARCH_USERS的查询变量,避免输入时实时触发请求 - 给
SEARCH_USERS添加skip选项,当searchQuery为空时跳过查询,减少无用请求
- 新增
修正数据逻辑与状态提示
- 明确区分「未搜索」「搜索无结果」「无用户」三种场景,分别处理显示内容
- 搜索无结果时,不再回退显示所有用户,而是展示对应提示文本
添加清空功能
- 新增清空按钮,点击后重置输入框和搜索状态,恢复显示全部用户
修改后的完整代码
import { useQuery } from "@apollo/client"; import { GET_ALL_USERS, SEARCH_USERS } from "../graphql/Queries"; import { useState } from 'react'; const UsersTable = () => { // 输入框实时值 const [search, setSearch] = useState(''); // 待提交的搜索关键词,控制查询触发 const [searchQuery, setSearchQuery] = useState(''); const { data: allUsersData, error: allUsersError, loading: allUsersLoading } = useQuery(GET_ALL_USERS); const { data: searchedData, error: searchedError, loading: searchedLoading } = useQuery(SEARCH_USERS, { variables: { name: searchQuery }, // 搜索关键词为空时跳过查询 skip: !searchQuery }); const allUsers = allUsersData?.allUsers || []; const searchedUsers = searchedData?.searchedUsers || []; // 处理表单提交,触发搜索 const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); setSearchQuery(search.trim()); }; // 清空搜索状态 const handleClear = () => { setSearch(''); setSearchQuery(''); }; return ( <div> {/* 搜索区域 */} <form onSubmit={handleSubmit}> <input type="text" placeholder='Search for user' value={search} onChange={e => setSearch(e.target.value)} /> <button type="submit">Search</button> {/* 清空按钮 */} {searchQuery && <button type="button" onClick={handleClear}>清空</button>} </form> {/* 加载状态提示 */} {(allUsersLoading || searchedLoading) && <p>加载中...</p>} {/* 错误提示 */} {(allUsersError || searchedError) && <p>加载用户失败,请稍后重试</p>} {/* 表格区域 */} <table className="w-full text-left"> <thead> <tr> <th>Name</th> <th>Username</th> <th>Age</th> </tr> </thead> <tbody> {/* 场景1:未执行搜索,显示所有用户 */} {!searchQuery && allUsers.length > 0 && allUsers.map((user: any) => ( <tr key={user.id}> <td>{user.name}</td> <td>{user.username}</td> <td>{user.age}</td> </tr> ))} {/* 场景2:执行了搜索,有结果则显示 */} {searchQuery && searchedUsers.length > 0 && searchedUsers.map((user: any) => ( <tr key={user.id}> <td>{user.name}</td> <td>{user.username}</td> <td>{user.age}</td> </tr> ))} {/* 场景3:搜索无结果 */} {searchQuery && searchedUsers.length === 0 && ( <tr> <td colSpan={3} style={{ textAlign: 'center' }}> 未找到包含「{searchQuery}」的用户 </td> </tr> )} {/* 场景4:数据库无任何用户 */} {!searchQuery && allUsers.length === 0 && ( <tr> <td colSpan={3} style={{ textAlign: 'center' }}> 未找到用户 </td> </tr> )} </tbody> </table> </div> ); }; export default UsersTable;
内容的提问来源于stack exchange,提问作者YoungInventa
相关产品推荐
相关产品推荐

