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

React Router SSR中useLocation()报错,求前后端兼容解决方案

问题描述

我按照React Router官方的SSR(非数据路由)方案实现服务端渲染,服务端代码如下:

<StaticRouter location={req.url}>
  <Routes>
    // ...
  </Routes>
</StaticRouter>

但我的路由组件SceneButton调用useLocation()时抛出错误:

useLocation() may be used only in the context of a <Router> component.

SceneButton代码如下:

import React from 'react'
import { useLocation } from 'react-router'

export function SceneButton(props: SceneButtonProps) {
  const location = useLocation()
  // ...
  return <button>Scene</button>
}

需要实现前后端均可正常获取location的方案,且因应用规模较大,无法重写为React Router推荐的Remix框架。

解决方案

1. 确保路由上下文覆盖所有使用路由钩子的组件

服务端渲染时,所有调用useLocation、useNavigate等路由钩子的组件,必须被StaticRouter(从react-router-dom/server导入)完全包裹,不能有组件脱离这个上下文单独渲染。

2. 客户端与服务端路由组件对应

  • 服务端:用StaticRouter传入请求的req.url,作为路由上下文的来源
  • 客户端:用BrowserRouter(或HashRouter)包裹整个应用,保证客户端渲染时路由上下文正常生效

示例代码结构:

// 服务端入口
import { StaticRouter } from 'react-router-dom/server';

function renderServerApp(req) {
  return ReactDOMServer.renderToString(
    <StaticRouter location={req.url}>
      {/* 所有需要路由上下文的组件都在这里面 */}
      <App />
    </StaticRouter>
  );
}

// 客户端入口
import { BrowserRouter } from 'react-router-dom';

ReactDOM.hydrateRoot(
  document.getElementById('root'),
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

3. 处理脱离路由上下文的组件

如果SceneButton是全局组件(比如全局弹窗、导航栏),需要确保它始终在路由组件的包裹范围内,不要在Router外部单独渲染。

如果确实需要在某些场景下脱离上下文,可以通过props手动传递location:

// 修改SceneButton,支持传入location
export function SceneButton(props: SceneButtonProps & { location?: Location }) {
  // 优先使用传入的location,否则调用钩子
  const location = props.location ?? useLocation();
  // ...
  return <button>Scene</button>;
}

// 服务端传递location
const serverLocation = new URL(req.url, `http://${req.headers.host}`);
<StaticRouter location={req.url}>
  <SceneButton location={{ pathname: serverLocation.pathname, search: serverLocation.search }} />
</StaticRouter>

// 客户端在路由内传递location
import { useLocation } from 'react-router-dom';

function PageComponent() {
  const location = useLocation();
  return <SceneButton location={location} />;
}

4. 检查版本一致性

确保react-router和react-router-dom的版本完全一致,且为v6及以上版本,v6之前的SSR方案存在上下文兼容问题,容易导致此类错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:08:08