【问题标题】:How to type the StaticRouterContext from react-router-dom in Typescript?如何在 Typescript 中从 react-router-dom 键入 StaticRouter 上下文?
【发布时间】:2021-04-14 08:13:26
【问题描述】:

我正在为我的应用程序执行 SSR(仅适用于机器人)。

<App/> 的渲染可能会导致找不到路由。

我需要检测该渲染何时以NOT_FOUND 路由结束,以便我可以从我的express 服务器返回res.sendStatus(404);

我从react-router 的官方文档中关注this tutorial

我有一个“catch all”路由,它将呈现 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);

&lt;StaticRouter&gt; 组件的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 对象?到目前为止,我还无法从任何地方导入StaticRouterContextStaticContext

【问题讨论】:

    标签: reactjs typescript react-router react-router-dom server-side-rendering


    【解决方案1】:

    刚刚找到了处理这个问题的方法。

    我只安装了以下软件包:

    "@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 类型,该类型在StaticRouterRouteProps 中使用。

    这是来自@types/react-routerStaticContext 类型:

    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);
    

    【讨论】:

      猜你喜欢
      • 2022-01-25
      • 2021-05-09
      • 1970-01-01
      • 2021-05-10
      • 2017-12-05
      • 2017-10-22
      • 2017-09-26
      • 2021-03-30
      • 2023-01-12
      相关资源
      最近更新 更多