You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:31:41