React搜索问题:未搜索时提前显示无结果页面如何修复
问题描述
开发带电影搜索功能的React页面时,遇到NotFoundPage组件在未执行搜索操作前就显示“无结果”提示的问题。希望仅在执行搜索后未找到结果时才展示该组件,求错误原因及修复方法。
现有代码
MoviesPage组件
import { useState, lazy, useEffect } from 'react'; import * as movieAPI from '../../../services/movie-api'; import { Gallery } from 'components/Gallery/Gallery'; import { SearchForm, Button, Label, Input } from './MoviesPage.styled'; import { useSearchParams, useLocation } from 'react-router-dom'; const NotFoundPage = lazy(() => import('../NotFound/NotFoundPage.js')); export default function MoviesPage() { const [searchQuery, setSearchQuery] = useState(''); const [data, setData] = useState(null); // eslint-disable-next-line no-unused-vars let [_, setSearchParams] = useSearchParams(); const handleInputChange = e => { setSearchQuery(e.currentTarget.value); }; const { search } = useLocation(); useEffect(() => { if (!search) { return; } movieAPI.fetchSearch(search.slice(7)).then(setData); }, [search]); const handleSubmit = e => { e.preventDefault(); const normalizeSearchQuery = searchQuery.trim().toLowerCase(); if (!normalizeSearchQuery) { return; } movieAPI.fetchSearch(normalizeSearchQuery).then(setData); setSearchParams(`query=${normalizeSearchQuery}`); // setSearchQuery(''); }; return ( <> <SearchForm onSubmit={handleSubmit}> <Input type="text" name="searchQuery" autoComplete="off" autoFocus placeholder="Search movies" value={searchQuery} onChange={handleInputChange} /> <Button type="submit"> <Label>Search</Label> </Button> </SearchForm> {data?.results.length > 0 ? <Gallery data={data} /> : <NotFoundPage />} </> ); }
NotFoundPage组件
import { Link } from 'react-router-dom'; function NotFoundPage() { return ( <div> <h2> Results not found :(</h2> <p> <Link to="/">Back</Link> </p> </div> ); } export default NotFoundPage;
错误原因
初始状态下data为null,页面首次渲染时data?.results.length > 0的判断结果为false(data为null时,data?.results是undefined,不存在length属性,整个表达式逻辑为假),因此会直接渲染NotFoundPage组件。
修复方案
新增一个状态标记是否已执行过搜索操作,只有当搜索执行后,才根据结果判断是否展示NotFoundPage。
修改后的MoviesPage组件代码
import { useState, lazy, useEffect } from 'react'; import * as movieAPI from '../../../services/movie-api'; import { Gallery } from 'components/Gallery/Gallery'; import { SearchForm, Button, Label, Input } from './MoviesPage.styled'; import { useSearchParams, useLocation } from 'react-router-dom'; const NotFoundPage = lazy(() => import('../NotFound/NotFoundPage.js')); export default function MoviesPage() { const [searchQuery, setSearchQuery] = useState(''); const [data, setData] = useState(null); const [isSearched, setIsSearched] = useState(false); // 新增:标记是否已执行搜索 let [_, setSearchParams] = useSearchParams(); const handleInputChange = e => { setSearchQuery(e.currentTarget.value); }; const { search } = useLocation(); useEffect(() => { if (!search) { setIsSearched(false); // 无搜索参数时重置搜索状态 return; } movieAPI.fetchSearch(search.slice(7)).then(res => { setData(res); setIsSearched(true); // URL参数触发搜索后标记为已搜索 }); }, [search]); const handleSubmit = e => { e.preventDefault(); const normalizeSearchQuery = searchQuery.trim().toLowerCase(); if (!normalizeSearchQuery) { return; } setIsSearched(true); // 点击搜索按钮后标记为已搜索 movieAPI.fetchSearch(normalizeSearchQuery).then(setData); setSearchParams(`query=${normalizeSearchQuery}`); // setSearchQuery(''); }; return ( <> <SearchForm onSubmit={handleSubmit}> <Input type="text" name="searchQuery" autoComplete="off" autoFocus placeholder="Search movies" value={searchQuery} onChange={handleInputChange} /> <Button type="submit"> <Label>Search</Label> </Button> </SearchForm> {/* 仅在已搜索时,根据结果展示对应组件 */} {isSearched ? ( data?.results.length > 0 ? <Gallery data={data} /> : <NotFoundPage /> ) : null} </> ); }
修复逻辑说明
- 新增
isSearched状态,初始值为false,表示未执行过搜索 - 点击搜索按钮或通过URL参数触发搜索时,将
isSearched设为true - 渲染阶段:只有
isSearched为true时,才根据搜索结果展示Gallery或NotFoundPage;未搜索时不渲染任何结果相关组件 - 当URL无搜索参数时(比如首次进入页面),重置
isSearched为false,避免残留状态影响显示
内容的提问来源于stack exchange,提问作者nika
相关产品推荐
相关产品推荐

