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

如何通过React Router v6实现跨组件监听状态变化

解决方案:在React Router v6中让子组件监听父组件状态变化

针对你的场景,有两种简单且实用的方案可以实现Page组件监听App中searchQuery的变化:

方案一:使用React Context共享状态

这是最直接的跨组件状态共享方式,因为App作为父路由组件包裹着<Outlet>,通过Context可以将searchQuery的状态和更新方法传递给所有子路由组件(包括Page)。

步骤1:创建搜索状态Context

// SearchContext.tsx
import { createContext, useContext, useState, ReactNode } from 'react';

type SearchContextType = {
  searchQuery: string;
  setSearchQuery: (query: string) => void;
};

const SearchContext = createContext<SearchContextType | undefined>(undefined);

export const SearchProvider = ({ children }: { children: ReactNode }) => {
  const [searchQuery, setSearchQuery] = useState<string>("");
  
  return (
    <SearchContext.Provider value={{ searchQuery, setSearchQuery }}>
      {children}
    </SearchContext.Provider>
  );
};

export const useSearch = () => {
  const context = useContext(SearchContext);
  if (!context) {
    throw new Error('useSearch must be used within a SearchProvider');
  }
  return context;
};

步骤2:在App组件中使用Provider

修改App.tsx,用SearchProvider包裹<Outlet>(或整个App内容):

// App.tsx 
import { useSearch } from './SearchContext';
import { Outlet } from 'react-router-dom';

function App() {
  const { searchQuery, setSearchQuery } = useSearch();

  return (
    <>
      <AppBar component="nav">
        {/* 输入框直接使用Context里的setSearchQuery */}
        <input
          type="text"
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          placeholder="搜索..."
        />
      </AppBar>
      <Outlet />
    </>
  );
}

同时在路由外层包裹SearchProvider(index.tsx):

// index.tsx
import { SearchProvider } from './SearchContext';

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<SearchProvider><App /></SearchProvider>}>
      <Route path="page" element={<Page />}></Route>
    </Route>
  )
);

步骤3:在Page组件中消费状态

// Page.tsx
import { useSearch } from './SearchContext';

function Page() {
  const { searchQuery } = useSearch();

  return (
    <div>
      当前搜索关键词:{searchQuery}
      {/* 这里可以直接使用searchQuery,它会自动跟随App中的变化更新 */}
    </div>
  );
}

方案二:将搜索状态同步到URL搜索参数

如果希望搜索状态能通过URL分享、刷新页面后保留,推荐使用React Router v6的useSearchParams钩子,将searchQuery和URL的查询参数绑定。

步骤1:在App组件中同步搜索状态到URL

// App.tsx 
import { Outlet, useSearchParams } from 'react-router-dom';

function App() {
  const [searchParams, setSearchParams] = useSearchParams();
  // 从URL参数中读取初始搜索值
  const searchQuery = searchParams.get('q') || "";

  const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const query = e.target.value;
    if (query) {
      setSearchParams({ q: query });
    } else {
      // 清空搜索参数
      searchParams.delete('q');
      setSearchParams(searchParams);
    }
  };

  return (
    <>
      <AppBar component="nav">
        <input
          type="text"
          value={searchQuery}
          onChange={handleSearchChange}
          placeholder="搜索..."
        />
      </AppBar>
      <Outlet />
    </>
  );
}

步骤2:在Page组件中监听URL参数变化

// Page.tsx
import { useSearchParams } from 'react-router-dom';

function Page() {
  const [searchParams] = useSearchParams();
  const searchQuery = searchParams.get('q') || "";

  return (
    <div>
      当前搜索关键词:{searchQuery}
      {/* 当URL中的q参数变化时,searchQuery会自动更新 */}
    </div>
  );
}

方案对比

  • React Context方案:适合不需要将搜索状态同步到URL的场景,实现简单,状态更新更直接。
  • URL搜索参数方案:适合需要分享搜索结果链接、刷新页面保留状态的场景,符合路由的设计语义。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:16:05