React Router 是 React 生态系统中最流行的路由解决方案,它使开发者能够构建单页应用(SPA)并管理应用中的导航和视图渲染。作为 React 应用的核心导航控制中枢,React Router 经历了多个版本的迭代,目前主要分为 v5 和 v6 两个主要版本分支。
React Router 主要由以下核心包构成:
Router 组件是 React Router 的核心,它为整个应用提供路由上下文(Routing Context)。根据不同的运行环境和需求,React Router 提供了多种 Router 实现。
/home/about
的干净 URLBrowserRouter 内部使用 history
库的 createBrowserHistory
方法创建历史记录对象:
import { createBrowserHistory } from 'history';
const history = createBrowserHistory({
window: window, // 默认使用全局 window 对象
});
import { BrowserRouter } from 'react-router-dom';
function App() {
return (
{/* 路由配置 */}
);
}
对于使用 BrowserRouter 的应用,服务器需要配置 URL 回退(以 Nginx 为例):
location / {
try_files $uri $uri/ /index.html;
}
#
)实现路由http://example.com/#/home
的 URLHashRouter 内部使用 history
库的 createHashHistory
方法:
import { createHashHistory } from 'history';
const history = createHashHistory();
import { HashRouter } from 'react-router-dom';
function App() {
return (
{/* 路由配置 */}
);
}
#/home/about
(默认)#home/about
#!/home/about
(旧式,不推荐)使用 history
库的 createMemoryHistory
方法:
import { createMemoryHistory } from 'history';
const history = createMemoryHistory({
initialEntries: ['/'], // 初始路由栈
initialIndex: 0, // 初始位置
});
import { MemoryRouter } from 'react-router-dom';
function App() {
return (
{/* 路由配置 */}
);
}
单元测试:
test('navigates to about page', () => {
render(
<MemoryRouter initialEntries={['/']}>
<App />
</MemoryRouter>
);
// 测试断言
});
React Native 应用(与 react-router-native 配合使用)
import { NativeRouter } from 'react-router-native';
function App() {
return (
{/* 路由配置 */}
);
}
import { StaticRouter } from 'react-router-dom/server';
function handleRequest(req, res) {
const html = renderToString(
<StaticRouter location={req.url}>
<App />
</StaticRouter>
);
// 返回渲染结果
}
// 服务器端代码(Node.js Express 示例)
import express from 'express';
import { StaticRouter } from 'react-router-dom/server';
const app = express();
app.get('*', (req, res) => {
const markup = renderToString(
);
res.send(`
${markup}
`);
});
特性 | BrowserRouter | HashRouter | MemoryRouter | NativeRouter | StaticRouter |
---|---|---|---|---|---|
URL 类型 | 干净路径 | 带 hash | 无 | 原生路径 | 无 |
需要服务器配置 | 是 | 否 | 否 | 否 | 是 |
浏览器历史记录 | 支持 | 支持 | 不支持 | 平台相关 | 不支持 |
适用环境 | 浏览器 | 浏览器 | 测试/非浏览器 | React Native | 服务器 |
SEO 友好性 | 高 | 低 | 无 | 无 | 高 |
典型使用场景 | 生产Web应用 | 旧版浏览器 | 测试/SSR | 移动应用 | 服务器渲染 |
BrowserRouter:
HashRouter:
MemoryRouter:
NativeRouter:
StaticRouter:
可以创建自定义 history 对象并传递给 Router 组件:
import { createBrowserHistory } from 'history';
import { Router } from 'react-router-dom';
const customHistory = createBrowserHistory({
basename: '/admin',
// 其他配置...
});
function App() {
return (
<Router history={customHistory}>
{/* 路由配置 */}
</Router>
);
}
实现动态基础路径(如多租户应用):
function App() {
const [basename, setBasename] = useState('/tenant1');
return (
{/* 路由内容 */}
);
}
虽然不推荐,但在特殊场景下可以嵌套 Router:
function App() {
return (
{/* 主应用路由 */}
{/* 嵌套独立路由 */}
} />
);
}
结合 localStorage 实现路由状态持久化:
const PERSISTENT_ROUTES = ['/user', '/settings'];
function PersistentRouter({ children }) {
const [location, setLocation] = useState(() => {
const saved = localStorage.getItem('lastRoute');
return PERSISTENT_ROUTES.includes(saved) ? saved : '/';
});
return (
<MemoryRouter
initialEntries={[location]}
initialIndex={0}
>
<LocationListener onLocationChange={setLocation} />
{children}
</MemoryRouter>
);
}
function LocationListener({ onLocationChange }) {
const location = useLocation();
useEffect(() => {
if (PERSISTENT_ROUTES.includes(location.pathname)) {
localStorage.setItem('lastRoute', location.pathname);
}
onLocationChange(location.pathname);
}, [location]);
return null;
}
现代Web应用:
静态网站/无服务器控制:
React Native 应用:
SSR 应用:
代码分割 + 懒加载:
const Home = lazy(() => import('./Home'));
}> } />
路由预加载:
// 鼠标悬停时预加载
function PreloadLink({ to, children }) {
const navigate = useNavigate();
return (
<Link
to={to}
onMouseEnter={() => import('./Page')}
onClick={(e) => {
e.preventDefault();
import('./Page').then(module => {
navigate(to, { state: { module } });
});
}}
>
{children}
</Link>
);
}
路由缓存策略:
function CachedRoute({ path, element }) {
const location = useLocation();
const [cache, setCache] = useState({});
useEffect(() => {
if (!cache[path]) {
setCache(prev => ({ ...prev, [path]: element }));
}
}, [path]);
return location.pathname === path ? element : cache[path] || null;
}
问题:使用 BrowserRouter 时,刷新非根路由返回 404
解决方案:
devServer: {
historyApiFallback: true,
}
location / {
try_files $uri $uri/ /index.html;
}
问题:导航返回时滚动位置丢失
解决方案:
{/* 其他内容 */}
function ScrollRestoration() {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo(0, 0);
}, [pathname]);
return null;
}
实现方案:
import { CSSTransition, TransitionGroup } from 'react-transition-group';
function AnimatedRoutes() {
const location = useLocation();
return (
{/* 路由配置 */}
);
}
/* CSS */
.fade-enter { opacity: 0; }
.fade-enter-active { opacity: 1; transition: opacity 300ms; }
.fade-exit { opacity: 1; }
.fade-exit-active { opacity: 0; transition: opacity 300ms; }
引入新 Router 组件:
用法基本不变
用于自定义历史记录简化嵌套路由:
路由定义方式变化:
迁移到
从 v5 到 v6 的主要变化:
Router 包装:
// v5
import { BrowserRouter } from 'react-router-dom';
// v6 (相同)
import { BrowserRouter } from 'react-router-dom';
自定义 history:
// v5
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';
// v6
import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom';
import { createBrowserHistory } from 'history';
Basename 处理:
graph TD
A[选择 Router 类型] --> B{是否浏览器环境?}
B -->|是| C{需要 SEO/干净URL?}
B -->|否| D{是否 React Native?}
C -->|是| E[BrowserRouter + 服务器配置]
C -->|否| F[HashRouter]
D -->|是| G[NativeRouter]
D -->|否| H[MemoryRouter]
E --> I{是否服务器渲染?}
I -->|是| J[StaticRouter (服务端) + BrowserRouter (客户端)]
更智能的路由预加载:
Web 标准集成:
微前端友好设计:
性能持续优化:
React Router 作为 React 生态中最核心的路由解决方案,随着 Web 应用的不断发展,其 Router 组件也将持续演进,为开发者提供更强大、更灵活的路由管理能力。理解不同 Router 类型的特性和适用场景,将帮助开发者构建更健壮、更高效的前端应用架构。