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

React开发问题:如何实现Navbar组件与Home组件的搜索数据联动并仅在Home页渲染搜索结果

用Redux实现跨组件搜索状态共享(适配你的现有React项目)

既然你已经在使用Redux处理用户认证了,那直接用它来管理搜索状态就是最顺手的方案——完美解决非直接父子组件的状态传递问题,而且不用引入新的依赖。下面是一步步的实现指南:

1. 添加搜索相关的Redux模块

首先在你的redux目录下新建search文件夹,用来管理搜索状态:

redux/search/searchActions.js

export const SET_SEARCH_QUERY = 'SET_SEARCH_QUERY';

export const setSearchQuery = (query) => ({
  type: SET_SEARCH_QUERY,
  payload: query
});

redux/search/searchReducer.js

import { SET_SEARCH_QUERY } from './searchActions';

const initialState = {
  query: ''
};

export const searchReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_SEARCH_QUERY:
      return {
        ...state,
        query: action.payload
      };
    default:
      return state;
  }
};

合并到根Reducer

找到你的根Reducer文件(比如redux/rootReducer.js),把搜索reducer加进去:

import { combineReducers } from 'redux';
import { authReducer } from './auth/authReducer';
import { searchReducer } from './search/searchReducer';

export const rootReducer = combineReducers({
  auth: authReducer,
  search: searchReducer // 新增搜索状态模块
});

2. 修改NavbarComp组件,绑定搜索状态

更新NavbarComp.js,移除原来的input/setInput props,改用Redux来管理搜索值:

import { Layout } from "antd";
import { Link, useHistory } from "react-router-dom";
import Cookies from "js-cookie";
import { useDispatch, useSelector } from "react-redux";
import { logout } from "redux/auth/authActions";
import { setSearchQuery } from "redux/search/searchActions"; // 导入搜索action
import { Nav, Navbar, Form, FormControl } from "react-bootstrap";
const { Header } = Layout;

export const NavbarComp = () => {
  const history = useHistory();
  const cookie = Cookies.get('token');
  const dispatch = useDispatch();
  const searchQuery = useSelector(state => state.search.query); // 获取当前搜索值

  const logMeOut = (e) => {
    e.preventDefault();
    dispatch(logout());
    history.push('/');
  };

  const handleSearchChange = (e) => {
    dispatch(setSearchQuery(e.target.value)); // 实时更新Redux里的搜索状态
  };

  return (
    <>
      <Navbar bg="light" expand="lg">
        <Form className="d-flex">
          <FormControl 
            type="search" 
            placeholder="Search" 
            className="mr-2" 
            aria-label="Search" 
            value={searchQuery} // 绑定Redux状态到输入框
            onChange={handleSearchChange} // 监听输入变化
          />
        </Form>
        {/* 保留你原有的Navbar其他内容(比如登录/注销按钮) */}
      </Navbar>
    </>
  )
}

3. 修改Home组件,移除本地输入框并复用搜索状态

更新Home.js,删掉本地的搜索状态,直接从Redux获取搜索值并过滤数据:

import React from 'react';
import { Link } from "react-router-dom";
import { useSelector } from 'react-redux';
import { v4 as uuid_v4 } from "uuid";

export const Home = () => {
  const connected = useSelector(state => state.auth.user);
  const searchQuery = useSelector(state => state.search.query); // 从Redux拿搜索值
  const [flatsDefault, setFlatsDefault] = React.useState([]);

  React.useEffect(() => {
    getListing('real_estates')
  }, [])

  const getListing = async (url) => {
    const config = { method: 'GET' };
    const response = await fetch(`${process.env.REACT_APP_API_URL}/${url}`, config);
    const data = await response.json();
    setFlatsDefault(data)
  };

  // 用useMemo缓存过滤结果,避免重复计算
  const filteredFlats = React.useMemo(() => {
    if (!searchQuery) return flatsDefault;
    return flatsDefault.filter(flat => 
      flat.title.toLowerCase().includes(searchQuery.toLowerCase())
    );
  }, [searchQuery, flatsDefault]);

  return (
    <>
      {/* 移除原来的本地输入框 */}
      <div className="home-header">
        <div className="bg-img-desc">
          <h1>List of real estates</h1>
        </div>
      </div>
      <div className="container" style={{ padding: '0 3.5rem' }}>
        <ul className="row">
          {filteredFlats.length > 0 ? (
            filteredFlats.map(flat => (
              <li className="col-12 col-sm-6 col-md-4 col-lg-3 mb-4" key={uuid_v4()}>
                <div className="card h-100">
                  { flat.images_url && <img src={`${process.env.REACT_APP_API_URL}${flat.images_url[0]}`} className="card-img-top" alt=""/> }
                  <div className="card-body">
                    <h5>{flat.title}</h5>
                    <p>Price : {flat.price} €</p>
                    <p>location : {flat.location}</p>
                    {connected && <Link to={`/real_estates/${flat.id}`} className="btn btn-primary">Details</Link>}
                  </div>
                </div>
              </li>
            ))
          ) : (
            <h2>No properties found matching your search</h2>
          )}
        </ul>
      </div>
    </>)
}

4. 更新App.js,清理无用props

修改App.js里的NavbarComp调用,去掉不需要的props:

import React from 'react';
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Layout } from 'antd';
import { NavbarComp } from "components/NavbarComp";
import { Home } from "pages/Home";
import Realestate from "pages/Realestate";
import NewRealestate from "pages/NewRealestate";
import { Other } from "pages/Other";
import { Login } from "pages/Login";
import { Register } from "pages/Register";
import Profile from "pages/Profile";
import { useDispatch, useSelector } from 'react-redux';
import { getUser } from 'redux/auth/authActions';
import Cookies from 'js-cookie';

function App() {
  const dispatch = useDispatch();
  const user = useSelector(state => state.auth.user);

  React.useEffect(() => {
    dispatch(getUser(Cookies.get('id')))
  }, [dispatch]) // 修复依赖警告

  return (
    <Layout className="layout" style={{ backgroundColor: 'transparent' }}>
      <Router>
        <NavbarComp /> {/* 不再需要传递input/setInput props */}
        <Switch>
          {/* 你的路由配置保持不变 */}
          <Route exact path="/">
            <Home />
          </Route>
          <Route exact path="/real_estates/:id">
            <Realestate />
          </Route>
          <Route path="/new_real_estate">
            <NewRealestate />
          </Route>
          <Route path="/other">
            <Other />
          </Route>
          <Route exact path="/login" >
            <Login />
          </Route>
          <Route exact path="/register" >
            <Register />
          </Route>
          <Route exact path="/profile" >
            <Profile user={user} />
          </Route>
        </Switch>
      </Router>
    </Layout>
  );
}
export default App;

为什么选Redux?

因为你的项目已经集成了Redux,不需要额外引入Context API或其他状态库,保持技术栈一致性的同时,还能轻松扩展——未来如果有其他组件需要用到搜索状态,直接用useSelector获取即可。

另外用useMemo缓存过滤结果,避免每次渲染都重复执行过滤逻辑,能小幅度提升页面性能。

内容的提问来源于stack exchange,提问作者pedrofromperu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 10:37:40