React搜索功能如何实现无匹配结果时显示「未找到结果」提示
React搜索无匹配结果提示实现方案
核心逻辑是在现有渲染分支中新增判断:当用户已输入搜索关键词、且过滤后的结果数组长度为0时,渲染无结果提示即可,同时顺手修复原代码存在的搜索状态异步bug(原代码setSearchInput后立刻读取旧状态,会导致搜索匹配延迟一个字符的问题)。
具体修改点
- 修复
searchItems函数的状态异步问题:函数内不要使用刚触发更新的searchInput状态做判断,直接使用入参searchValue做过滤逻辑判断和关键词匹配,避免搜索结果和输入不同步。 - 调整结果区域渲染分支:原有逻辑仅判断「是否有搜索输入」,现在在「有输入」的分支下新增二级判断:如果过滤结果长度为0就渲染无结果提示,有结果再遍历渲染结果卡片。
- (可选优化)补上原代码已经定义但未使用的加载状态、接口错误状态渲染,提升交互完整性。
- 补全原代码缺失的初始赋值逻辑:接口拉取全量数据后,同步给
filteredResults赋初始值,避免页面初次加载时结果区域空白。
修改后完整代码
import { useState, useEffect } from 'react'; import axios from 'axios'; import { OutlinedInput, InputAdornment } from '@mui/material'; import SearchIcon from '@mui/icons-material/Search'; import { Link } from 'react-router-dom'; export default function SearchInput() { const [APIData, setAPIData] = useState([]); const [searchInput, setSearchInput] = useState(''); const [filteredResults, setFilteredResults] = useState([]); const [error, setError] = useState(false); const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { const fetchData = async () => { setError(false); setIsLoaded(true); try{ const response = await axios("/posts"); setAPIData(response.data); // 初始拉取数据后给过滤结果赋默认值 setFilteredResults(response.data); } catch(error) { setError(true); console.error(error); } setIsLoaded(false); }; fetchData(); }, []); const searchItems = (searchValue) => { setSearchInput(searchValue) // 修复:直接使用入参searchValue判断,避免状态异步导致的匹配延迟 if (searchValue !== '') { const filteredData = APIData.filter((post) => { return Object.values(post).join('').toLowerCase().includes(searchValue.toLowerCase()) }) setFilteredResults(filteredData) } else{ setFilteredResults(APIData) } } return ( <div style={{ padding: 20 }}> <OutlinedInput className="SearchInput" placeholder='Search...' onChange={(e) => searchItems(e.target.value)} endAdornment={ <InputAdornment position="end"> <SearchIcon /> </InputAdornment> } /> <div style={{ marginTop: 20 }}> {/* 加载状态渲染 */} {isLoaded && <div>数据加载中...</div>} {/* 接口错误渲染 */} {error && <div>数据加载失败,请稍后重试</div>} {/* 数据加载完成且无报错时渲染主内容 */} {!isLoaded && !error && ( <> {searchInput.length > 0 ? ( // 有搜索输入时的逻辑分支 filteredResults.length === 0 ? ( // 无匹配结果,渲染提示 <div style={{textAlign: 'center', color: '#666', padding: '40px 0'}}> no results found(未找到结果) </div> ) : ( // 有匹配结果,遍历渲染卡片 filteredResults.map((post) => { return ( <div className="card" key={post._id}> <div className="card-content"> <Link to={`/post/${post._id}`} className="link"> <h2 className="results-title"> {post.title} </h2> <ol className="card-username"> {post.username} </ol> </Link> </div> </div> ) }) ) ) : ( // 无搜索输入时,渲染全量数据 APIData.map((post) => { return ( <article className="card" key={post._id}> <div className="card-content"> <Link to={`/post/${post._id}`} className="link"> <h2 className="card-name"> {post.title} </h2> <ol className="card-username"> {post.username} </ol> </Link> </div> </article> ) }) )} </> )} </div> </div> ) }
补充说明
无结果提示的样式可以根据项目设计规范自行调整,示例中仅写了基础的居中、灰色文字样式。如果不需要加载、错误状态的提示,可以直接删除对应判断分支,仅保留无搜索结果的判断逻辑即可。
内容的提问来源于stack exchange,提问作者sultan.h
相关产品推荐
相关产品推荐

