React Router v5下如何传递搜索结果给组件?是否需新增搜索路由?
解决搜索结果传递给HomeScreen的问题(React Router v5)
你不需要创建单独的搜索路由,通过URL查询参数或者Redux状态管理就能实现搜索结果替代HomeScreen原有数据的需求,以下是具体方案:
方案一:使用URL查询参数(推荐)
利用URL的search参数传递搜索关键词,HomeScreen读取参数后请求对应结果,无需新增路由。
修改Header.js
import { useHistory } from 'react-router-dom'; // ...其他导入 function Header() { const userLogin = useSelector((state) => state.userLogin); const { userInfo } = userLogin; const [searchQuery, setSearchQuery] = useState(""); // 存输入的搜索关键词 const debounce = useDebounce(searchQuery, 500); const dispatch = useDispatch(); const history = useHistory(); // 新增useHistory钩子 const logoutHandler = () => { dispatch(logout()); }; // 处理输入变化 const handleInputChange = (e) => { setSearchQuery(e.target.value); }; // 处理搜索按钮点击 const handleSearchSubmit = () => { if (searchQuery.trim()) { // 跳转到首页并携带搜索参数 history.push(`/?search=${encodeURIComponent(searchQuery)}`); } else { // 无关键词时回到首页默认状态 history.push("/"); } }; return ( <div> <Navbar bg="dark" variant="dark" className="navCustom"> <Container> <LinkContainer to="/"> <Navbar.Brand>eCommerce</Navbar.Brand> </LinkContainer> <Form className="d-flex" onSubmit={(e) => {e.preventDefault(); handleSearchSubmit();}}> <Form.Control type="search" placeholder="Search" className="me-2" aria-label="Search" value={searchQuery} onChange={handleInputChange} /> <Button variant="outline-success" type="submit">Search</Button> </Form> {/* ...其他Header内容 */} </Container> </Navbar> </div> ); }
修改HomeScreen.js
import { useLocation } from 'react-router-dom'; // ...其他导入 function HomeScreen() { const dispatch = useDispatch(); const productList = useSelector((state) => state.productList); const { error, loading, products } = productList; const [searchResults, setSearchResults] = useState([]); const location = useLocation(); // 解析URL的搜索参数 const getSearchQuery = () => { const params = new URLSearchParams(location.search); return params.get("search") || ""; }; useEffect(() => { const searchQuery = getSearchQuery(); if (searchQuery) { // 请求搜索结果 axios.get(`/api/search/?search=${searchQuery}`).then((response) => { setSearchResults(response.data[0]); }); } else { // 无搜索参数时加载默认产品列表 dispatch(listProducts()); setSearchResults([]); // 清空搜索结果 } }, [dispatch, location.search]); // 监听URL参数变化 return ( <div> {searchResults.length > 0 ? ( <Row> {searchResults.map((product) => ( <Col key={product._id} sm={12} md={6} lg={4} xl={3}> <Product product={product} /> </Col> ))} </Row> ) : ( <Row> {loading ? ( <p>加载中...</p> ) : error ? ( <p>{error}</p> ) : ( products && products.map((product) => ( <Col key={product._id} sm={12} md={6} lg={4} xl={3}> <Product product={product} /> </Col> )) )} </Row> )} </div> ); } export default HomeScreen;
方案二:使用Redux管理搜索状态
如果你的项目已经在用Redux,可以把搜索关键词和结果存在全局状态里,让Header和HomeScreen共享:
1. 创建搜索相关的Redux模块
// actions/searchActions.js export const SET_SEARCH_QUERY = 'SET_SEARCH_QUERY'; export const SET_SEARCH_RESULTS = 'SET_SEARCH_RESULTS'; export const setSearchQuery = (query) => ({ type: SET_SEARCH_QUERY, payload: query, }); export const setSearchResults = (results) => ({ type: SET_SEARCH_RESULTS, payload: results, }); // reducers/searchReducer.js import { SET_SEARCH_QUERY, SET_SEARCH_RESULTS } from '../actions/searchActions'; const initialState = { query: '', results: [], }; export default function searchReducer(state = initialState, action) { switch (action.type) { case SET_SEARCH_QUERY: return { ...state, query: action.payload }; case SET_SEARCH_RESULTS: return { ...state, results: action.payload }; default: return state; } }
2. 修改Header.js
// ...其他导入 import { setSearchQuery, setSearchResults } from '../actions/searchActions'; function Header() { // ...原有代码 const searchQuery = useSelector((state) => state.search.query); const history = useHistory(); useEffect(() => { if (searchQuery.trim()) { axios.get(`/api/search/?search=${searchQuery}`).then((response) => { dispatch(setSearchResults(response.data[0])); }); } else { dispatch(setSearchResults([])); } }, [debounce, dispatch]); const handleInputChange = (e) => { dispatch(setSearchQuery(e.target.value)); }; // 点击搜索按钮跳回首页,确保HomeScreen渲染 const handleSearchSubmit = () => { history.push("/"); }; // ...返回JSX部分,将Form.Control的value绑定到searchQuery }
3. 修改HomeScreen.js
// ...其他导入 function HomeScreen() { const dispatch = useDispatch(); const productList = useSelector((state) => state.productList); const { error, loading, products } = productList; const searchResults = useSelector((state) => state.search.results); // 从Redux获取结果 useEffect(() => { dispatch(listProducts()); }, [dispatch]); // ...原有渲染逻辑不变,直接使用searchResults即可 }
为什么不需要单独搜索路由?
单独创建/search路由会让用户跳转到新页面,而在首页通过查询参数处理搜索,用户体验更连贯,同时URL也能保留搜索状态(刷新页面后不会丢失搜索结果)。
内容的提问来源于stack exchange,提问作者Khaled
相关产品推荐
相关产品推荐

