简体   繁体   English

React Typescript - 在路由中传递时如何将类型添加到 location.state

[英]React Typescript - How add Types to location.state when passed in a Route

I am getting an error when I pass react-router props sent to a component in a Route because I have specific state that I pass this component but the error shows up in my Route.当我将 react-router props 传递给路由中的组件时出现错误,因为我有特定的状态,我传递了这个组件,但错误显示在我的路由中。

在此处输入图片说明

Here is the Route code:这是路由代码:

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

In another component I call this below在另一个组件中,我在下面称之为

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

Here is the code for the Component.这是组件的代码。 I finally got Typescript to compile this but I had to merge LocationState & TimelineState to get this to work.我终于得到了 Typescript 来编译它,但我必须合并 LocationState 和 TimelineState 才能让它工作。 But now Typescript throws the above screenshot when I send props to my FliplTimeline component.但是现在当我将道具发送到我的 FliplTimeline 组件时,Typescript 会抛出上面的屏幕截图。 Anyone have and idea how to fix this?任何人都知道如何解决这个问题?

history.tsx历史.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;

FliplTimeline.tsx翻转时间线.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>

Update: Added my history.tsx file in which I created my own history for React-Router.更新:添加了我的 history.tsx 文件,我在其中为 React-Router 创建了自己的历史记录。 Also added in the import statements.还添加在导入语句中。

Update: Tried to change my FliplTimeline component to have this interface更新:尝试将我的 FliplTimeline 组件更改为具有此界面

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

function FliplTimeline(props: RouteComponentProps ) {

I get 2 errors.我收到 2 个错误。 First one is this one and another that says that the shape of the props are wrong.第一个是这个,另一个说道具的形状是错误的。 Ideas?想法? 错误

Update: I was able to finally get the right props declaration for my component.更新:我终于能够为我的组件获得正确的 props 声明。

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

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

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

I was able to get it working.我能够让它工作。

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

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

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

Use RouteComponentProps and feed it the appropriate types for its generic.使用RouteComponentProps并为其通用提供适当的类型。 This article covers quite a bit: How to Use React Router in Typescript .这篇文章涵盖了很多内容:如何在 Typescript 中使用 React Router

Using React Router with TypeScript almost necessitates filling in the generics that React Router has.使用 React Router 和 TypeScript 几乎需要填写 React Router 的泛型。 Otherwise there isn't enough context to determine the types of everything.否则没有足够的上下文来确定所有内容的类型。 Compare to my example below.与我下面的示例进行比较。 I use useHistory and fill it with the type that I want to be made available.我使用useHistory并用我想要提供的类型填充它。 This would probably be your FliplTimelineLocationState that way the state property of history would be determinable to be of type FliplTimelineLocationState .这可能是您的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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM