【问题标题】:React Typescript - How add Types to location.state when passed in a RouteReact Typescript - 在路由中传递时如何将类型添加到 location.state
【发布时间】:2020-06-06 04:12:38
【问题描述】:

当我将 react-router props 发送到 Route 中的组件传递时出现错误,因为我具有传递此组件的特定状态,但错误显示在我的 Route 中。

这是路线代码:

<Route
    exact
    path='/flipltimeline'
    render={props => <FliplTimeline {...props} />

在另一个组件中我称之为下面

props.history.push(`/flipltimeline`, {
      Approval: singleFliplApprovals,
      InvestigationID,
      Unit: unit,
      Cost: cost
    });

这是组件的代码。我终于得到了 Typescript 来编译它,但我必须合并 LocationState 和 TimelineState 才能让它工作。但是现在,当我将道具发送到我的 FliplTimeline 组件时,Typescript 会抛出上面的屏幕截图。任何人都知道如何解决这个问题?

history.tsx

import { createBrowserHistory } from 'history';

let baseNameProd = '';

if (process.env.NODE_ENV !== 'production') {
  console.log('Looks like we are in development mode!');
  baseNameProd = '';
} else {
  baseNameProd = '/flipl';
}

const customHistory = createBrowserHistory({
  basename: baseNameProd
});

export default customHistory;

翻转时间线.tsx

import * as React from 'react';
import { History, LocationState } from 'history';

interface FliplTimelineLocationState {
  Approval: any;
  InvestigationID: number;
  Unit: string;
  Cost: number;
}

interface TimelineState{
  state: FliplTimelineLocationState;
}

interface Props {
  history: History;
  location: LocationState & TimelineState;
}

function FliplTimeline(props: Props) {
  return (
    <ModuleTemplate title='Status Timeline' subtitle=''>
      <FliplTimelineJumbotron className='bg-primary-darker shadow-4 line-height-serif-4'>
        <div className='grid-row'>
          <div className='grid-col-4'>
            <span
              className='font-mono-2xl text-white'
              style={{
                verticalAlign: 'middle'
              }}
            >
              FLIPL{' '}
            </span>
            <span
              className='font-mono-xl text-gold'
              style={{
                verticalAlign: 'middle'
              }}
            >
              {props.location.state.InvestigationID}
            </span>

更新:添加了我的 history.tsx 文件,我在其中为 React-Router 创建了自己的历史记录。也在导入语句中添加。

更新:尝试将我的 FliplTimeline 组件更改为具有此界面

import { RouteComponentProps } from 'react-router-dom'

function FliplTimeline(props: RouteComponentProps ) {

我收到 2 个错误。第一个是这个,另一个说道具的形状不对。想法?

更新:我终于能够为我的组件获得正确的道具声明。

import { RouteComponentProps } from 'react-router-dom';

interface FliplTimelineLocationState {
  Approval: any;
  InvestigationID: number;
  Unit: string;
  Cost: number;
}

function FliplTimeline(
  props: RouteComponentProps<{}, any, FliplTimelineLocationState | any>
)

【问题讨论】:

    标签: reactjs typescript react-router


    【解决方案1】:

    我能够让它工作。

    import { RouteComponentProps } from 'react-router-dom';
    
    interface FliplTimelineLocationState {
      Approval: any;
      InvestigationID: number;
      Unit: string;
      Cost: number;
    }
    
    function FliplTimeline(
      props: RouteComponentProps<{}, any, FliplTimelineLocationState | any>
    )
    

    【讨论】:

      【解决方案2】:

      使用RouteComponentProps 并为其泛型提供适当的类型。这篇文章涵盖了很多:How to Use React Router in Typescript.

      使用带有 TypeScript 的 React Router 几乎需要填写 React Router 所具有的泛型。否则没有足够的上下文来确定所有事物的类型。与我下面的示例进行比较。我使用useHistory 并用我希望可用的类型填充它。这可能是您的FliplTimelineLocationState,这样historystate 属性就可以确定为FliplTimelineLocationState 类型。

      import React, {MouseEventHandler} from "react";
      import {Route, RouteComponentProps, StaticContext, useHistory} from "react-router";
      import {BrowserRouter, Link} from "react-router-dom";
      
      interface IMyScreenRouteParams {
          foo: string;
      }
      
      // You don't have to extend, you could just use StaticContext
      interface IMyStaticContext extends StaticContext {
          bar: string;
      }
      
      interface IHistory {
          fizz: string;
      }
      
      const Nav = () => {
          const history = useHistory<IHistory>();
      
          const clickHanlder: MouseEventHandler = () => {
              history.push("/my-screen", {
                  fizz: "you said fizz"
              });
          };
      
          return (
              <nav>
                  <ul>
                      <li><Link to="/">Home</Link></li>
                      <li><Link to="/my-screen">My Screen</Link></li>
                      <li><button onClick={clickHanlder}>My Screen with state</button></li>
                      <li><Link to="/my-screen?q=hello">My Screen with query</Link></li>
                      <li><Link to="/my-screen/bob">My Screen using match</Link></li>
                  </ul>
                  <div>
                      <button onClick={() => history.goBack()}>Back</button>
                      <button onClick={() => history.push("/")}>Home</button>
                      <button onClick={() => history.goForward()}>Forward</button>
                  </div>
              </nav>
          );
      };
      
      const MyScreen = ({
          location,
          match,
          history,
          staticContext
      }: RouteComponentProps<IMyScreenRouteParams, IMyStaticContext, IHistory>) => (
          <div>
              <section>
                  <h2>Location</h2>
                  <p><code>location</code> has <code>IHistory</code> props.</p>
                  <pre><code>{JSON.stringify(location, null, 4)}</code></pre>
              </section>
              <section>
                  <h2>Match</h2>
                  <p><code>match</code> has <code>IMyScreenRouteParams</code> props.</p>
                  <pre><code>{JSON.stringify(match, null, 4)}</code></pre>
              </section>
              <section>
                  <h2>History</h2>
                  <p><code>history</code> has <code>IHistory</code> props.</p>
                  <pre><code>{JSON.stringify(history, null, 4)}</code></pre>
              </section>
              <section>
                  <h2>Static Context</h2>
                  <p><code>staticContext</code> has <code>IMyStaticContext</code> props or whatever static context your router has.</p>
                  <p>This is for a <a href="https://reacttraining.com/react-router/web/api/StaticRouter/context-object"><code>&lt;StaticRouter/&gt;</code></a>.</p>
                  <pre><code>{JSON.stringify(staticContext, null, 4)}</code></pre>
              </section>
          </div>
      );
      
      const Router = () => (
          <BrowserRouter>
              <div
                  style={{
                      display: "flex",
                      flexDirection: "row"
                  }}
              >
                  <Nav />
                  <main>
                      <Route exact path="/" component={() => (<div>Click something in the <code>&lt;nav/&gt;</code></div>)} />
                      <Route exact path="/my-screen" component={MyScreen} />
                      <Route exact path="/my-screen/:id" component={MyScreen} />
                  </main>
              </div>
          </BrowserRouter>
      );
      
      export default Router;
      

      【讨论】:

      • 感谢您的评论。我在这个中使用了一个类组件,我知道在这个例子中使用钩子是有区别的。我会尝试使用 RouteComponentProps。
      猜你喜欢
      • 2020-07-27
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 2021-05-16
      • 1970-01-01
      • 2022-10-08
      • 2018-08-28
      相关资源
      最近更新 更多