StaticRouter — это компонент из библиотеки React
Router, предназначенный для использования в средах, где нет браузерного
API для навигации, таких как сервер. В отличие от
BrowserRouter, который работает на клиенте и управляет
историей через API window.history,
StaticRouter предоставляет возможность создавать
маршрутизацию в статическом контексте, что необходимо для серверного
рендеринга (Server-Side Rendering, SSR).
StaticRouter имеет несколько ключевых пропсов, которые
управляют его поведением:
location Определяет текущий URL для
маршрутизации. Обычно это строка, содержащая путь запроса пользователя.
На сервере это может быть req.url из Express или любого
другого HTTP-сервера.
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>context Объект, который позволяет компонентам
внутри маршрутизатора взаимодействовать с серверной логикой. Например,
при использовании <Redirect> информация о
перенаправлении записывается в context, что позволяет
серверу корректно ответить HTTP-статусом 301 или 302.
const context = {};
const html = renderToString(
<StaticRouter location="/about" context={context}>
<App />
</StaticRouter>
);
if (context.url) {
res.writeHead(302, { Location: context.url });
res.end();
}basename Задает базовый путь, который будет добавлен ко всем маршрутам. Полезен для приложений, размещенных в поддиректории сайта.
| Характеристика | BrowserRouter | StaticRouter |
|---|---|---|
| Место использования | Клиент (браузер) | Сервер |
| История | Использует window.history |
Не использует историю |
| Навигация | Динамическая | Статическая, определяется пропсом location |
| Поддержка SSR | Нет | Да |
Ключевой момент: StaticRouter не умеет
управлять историей браузера. Его задача — предоставить контекст
маршрутизации для корректного рендеринга компонентов React на
сервере.
import express from 'express';
import { StaticRouter } from 'react-router-dom/server';
import { renderToString } from 'react-dom/server';
import App from './App';
const app = express();
app.get('*', (req, res) => {
const context = {};
const html = renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
if (context.url) {
res.redirect(301, context.url);
} else {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>SSR App</title>
</head>
<body>
<div id="root">${html}</div>
<script src="/bundle.js"></script>
</body>
</html>
`);
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
В этом примере:
location={req.url} передает путь запроса в
маршрутизатор.context используется для отслеживания перенаправлений
или ошибок.renderToString возвращает готовый HTML для
отправки клиенту.<Redirect> и контекстомПри использовании SSR <Redirect> не может напрямую
менять URL в браузере. Вместо этого он записывает информацию о редиректе
в объект context. Сервер проверяет context.url
и выполняет перенаправление с нужным HTTP-статусом.
import { Routes, Route, Navigate } from 'react-router-dom';
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/dashboard" element={<RequireAuth><Dashboard /></RequireAuth>} />
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
);
}
Если пользователь не аутентифицирован, компонент
RequireAuth может использовать
<Navigate> для перенаправления на
/login. На сервере это будет отражено через
context.url, что позволяет вернуть правильный
HTTP-ответ.
basename позволяет учитывать базовую часть URL, если
приложение размещено в поддиректории:
<StaticRouter location="/admin/users" context={context} basename="/admin">
<App />
</StaticRouter>
В этом случае маршруты внутри <App> будут
интерпретироваться относительно /admin.
В React Router v6 для SSR:
react-router-dom/server вместо обычного
react-router-dom.StaticRouter работает с renderToString или
renderToPipeableStream (React 18).context) обеспечивает передачу информации о
перенаправлениях и статусах страниц.import { renderToPipeableStream } from 'react-dom/server';
const stream = renderToPipeableStream(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>,
{
onShellReady() {
res.statusCode = context.statusCode || 200;
stream.pipe(res);
}
}
);
window или history напрямую.context
обеспечивает безопасное взаимодействие между сервером и
маршрутизатором.StaticRouter является ключевым инструментом для
построения универсальных React-приложений, где маршрутизация должна
работать как на сервере, так и на клиенте, обеспечивая корректный SSR и
управление HTTP-ответами.