如何在 Typescript 中从 react-router-dom 键入 StaticRouterContext?
How to type the StaticRouterContext from react-router-dom in Typescript?
我正在为我的应用做 SSR(仅限机器人)。
<App/>
的渲染可能会导致找不到路线。
我需要检测渲染何时在 NOT_FOUND
路由中结束,以便我可以从我的 express
服务器 return res.sendStatus(404);
。
我正在关注 this tutorial react-router
的官方文档。
我有一个“捕获所有”路由,它将呈现一个 404 页面并将该信息添加到 staticContext
:
AllRoutes.ts
<Route exact path={"*"} render={({ staticContext }) => {
if (staticContext) {
staticContext.statusCode = 404;
}
return <Page404/>;
}}/>
Route
组件的 render
属性内的 staticContext
对象推断的类型是:
而且它似乎只有 属性 是可选的 statusCode?: number
属性.
在SERVER端,我是这样做的:
ssrApp.tsx
import App from "@src/App";
import { renderToString } from "react-dom/server";
import { StaticRouter } from "react-router-dom";
// ...
const context = {}; // <<< WHAT TO TYPE THIS VARIABLE ?
const appHtml = renderToString(
<StaticRouter location={req.url} context={context}>
<App/>
</StaticRouter>
);
res.status(context.statusCode || 200).send(appHtml);
<StaticRouter>
组件的 context
属性的类型是 StaticRouterContext
:
它接受空的 const context= {};
属性。但是当我尝试从中访问 statusCode
属性 时它会抱怨。
这里提到的所有类型似乎都来自包 @types/react-router
或 @types/react-router-dom
,不太确定是哪个。
@types/react-router/index.d.ts
export interface StaticContext {
statusCode?: number;
}
export interface RouteComponentProps<
Params extends { [K in keyof Params]?: string } = {},
C extends StaticContext = StaticContext,
S = H.LocationState
> {
history: H.History<S>;
location: H.Location<S>;
match: match<Params>;
staticContext?: C;
}
如何输入我的 context
对象?到目前为止,我无法从任何地方导入 StaticRouterContext
或 StaticContext
。
刚刚找到了解决这个问题的方法。
我只安装了以下软件包:
"@types/react-router-dom": "^5.1.5" (AS DEV DEPENDENCY)
"react-router-dom": "^5.2.0" (AS REGULAR DEPENDENCY)
我无法导入我在问题中提到的类型,因为它们是在 @types/react-router
中定义的,它是 @types/react-router-dom
的内部依赖项,并且它们不会重新从后者导出。
以下是 @types/react-router
中从 @types/react-router-dom
重新导出的类型:
@types/react-router-dom/index.d.ts
我能做的:
我创建了自己的 MY_STATIC_CONTEXT
类型,它需要隐式扩展 @types/react-router
中定义的 StaticContext
类型,该类型在 StaticRouter
和 [=23] 中使用=].
这是 @types/react-router
中的 StaticContext
类型:
export interface StaticContext {
statusCode?: number;
}
所以我做到了:
type MY_STATIC_CONTEXT = {
statusCode?: number // THIS IS SO YOU EXTEND THE ORIGINAL TYPE,
ROUTE_NOT_FOUND: boolean // THIS IS MY CUSTOM PROP
}
现在,这是可能的:
ON_CLIENT - AllRoutes.ts
一个简单的类型声明允许我更新我的自定义道具 ROUTE_NOT_FOUND
。
<Route exact path={"*"} render={({ staticContext }) => {
if (staticContext) {
(staticContext as MY_STATIC_CONTEXT).statusCode = 404;
(staticContext as MY_STATIC_CONTEXT).ROUTE_NOT_FOUND = true;
}
return <Error404/>;
}}/>
ON_SERVER - ssrApp.tsx
const context: MY_STATIC_CONTEXT = {
ROUTE_NOT_FOUND: false
};
const appHtml = renderToString(
<StaticRouter location={req.url} context={context}>
<App/>
</StaticRouter>
));
if (context.ROUTE_NOT_FOUND) {
// DO SOMETHING
}
res.status(context.statusCode || 200).send(appHtml);
我正在为我的应用做 SSR(仅限机器人)。
<App/>
的渲染可能会导致找不到路线。
我需要检测渲染何时在 NOT_FOUND
路由中结束,以便我可以从我的 express
服务器 return res.sendStatus(404);
。
我正在关注 this tutorial react-router
的官方文档。
我有一个“捕获所有”路由,它将呈现一个 404 页面并将该信息添加到 staticContext
:
AllRoutes.ts
<Route exact path={"*"} render={({ staticContext }) => {
if (staticContext) {
staticContext.statusCode = 404;
}
return <Page404/>;
}}/>
Route
组件的 render
属性内的 staticContext
对象推断的类型是:
而且它似乎只有 属性 是可选的 statusCode?: number
属性.
在SERVER端,我是这样做的:
ssrApp.tsx
import App from "@src/App";
import { renderToString } from "react-dom/server";
import { StaticRouter } from "react-router-dom";
// ...
const context = {}; // <<< WHAT TO TYPE THIS VARIABLE ?
const appHtml = renderToString(
<StaticRouter location={req.url} context={context}>
<App/>
</StaticRouter>
);
res.status(context.statusCode || 200).send(appHtml);
<StaticRouter>
组件的 context
属性的类型是 StaticRouterContext
:
它接受空的 const context= {};
属性。但是当我尝试从中访问 statusCode
属性 时它会抱怨。
这里提到的所有类型似乎都来自包 @types/react-router
或 @types/react-router-dom
,不太确定是哪个。
@types/react-router/index.d.ts
export interface StaticContext {
statusCode?: number;
}
export interface RouteComponentProps<
Params extends { [K in keyof Params]?: string } = {},
C extends StaticContext = StaticContext,
S = H.LocationState
> {
history: H.History<S>;
location: H.Location<S>;
match: match<Params>;
staticContext?: C;
}
如何输入我的 context
对象?到目前为止,我无法从任何地方导入 StaticRouterContext
或 StaticContext
。
刚刚找到了解决这个问题的方法。
我只安装了以下软件包:
"@types/react-router-dom": "^5.1.5" (AS DEV DEPENDENCY)
"react-router-dom": "^5.2.0" (AS REGULAR DEPENDENCY)
我无法导入我在问题中提到的类型,因为它们是在 @types/react-router
中定义的,它是 @types/react-router-dom
的内部依赖项,并且它们不会重新从后者导出。
以下是 @types/react-router
中从 @types/react-router-dom
重新导出的类型:
@types/react-router-dom/index.d.ts
我能做的:
我创建了自己的 MY_STATIC_CONTEXT
类型,它需要隐式扩展 @types/react-router
中定义的 StaticContext
类型,该类型在 StaticRouter
和 [=23] 中使用=].
这是 @types/react-router
中的 StaticContext
类型:
export interface StaticContext {
statusCode?: number;
}
所以我做到了:
type MY_STATIC_CONTEXT = {
statusCode?: number // THIS IS SO YOU EXTEND THE ORIGINAL TYPE,
ROUTE_NOT_FOUND: boolean // THIS IS MY CUSTOM PROP
}
现在,这是可能的:
ON_CLIENT - AllRoutes.ts
一个简单的类型声明允许我更新我的自定义道具 ROUTE_NOT_FOUND
。
<Route exact path={"*"} render={({ staticContext }) => {
if (staticContext) {
(staticContext as MY_STATIC_CONTEXT).statusCode = 404;
(staticContext as MY_STATIC_CONTEXT).ROUTE_NOT_FOUND = true;
}
return <Error404/>;
}}/>
ON_SERVER - ssrApp.tsx
const context: MY_STATIC_CONTEXT = {
ROUTE_NOT_FOUND: false
};
const appHtml = renderToString(
<StaticRouter location={req.url} context={context}>
<App/>
</StaticRouter>
));
if (context.ROUTE_NOT_FOUND) {
// DO SOMETHING
}
res.status(context.statusCode || 200).send(appHtml);