[英]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
,这样history
的state
属性就可以确定为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><StaticRouter/></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><nav/></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.