Reactjs 在Typescript项目中实现react路由器PrivateRoute
以下是react router的一个示例,介绍如何为受保护的路由添加组件:Reactjs 在Typescript项目中实现react路由器PrivateRoute,reactjs,typescript,redux,react-redux,react-router,Reactjs,Typescript,Redux,React Redux,React Router,以下是react router的一个示例,介绍如何为受保护的路由添加组件: function PrivateRoute({ component: Component, ...rest }) { return ( <Route {...rest} render={props => fakeAuth.isAuthenticated ? ( <Component {...props} />
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
}
组件/privaterote
import { connect } from 'react-redux';
import { AppState } from 'app-types';
import PrivateRouteComponent from '../../components/PrivateRoute';
const mapStateToProps = (state: AppState) => {
const isSignedIn = state.user.isSignedIn;
return {
isSignedIn
};
};
const PrivateRoute = connect(
mapStateToProps,
null
)(PrivateRouteComponent);
export default PrivateRoute;
import * as React from 'react';
import {
Route,
Redirect,
} from 'react-router-dom';
interface PrivateRouteProps {
// tslint:disable-next-line:no-any
component: any;
isSignedIn: boolean;
// tslint:disable-next-line:no-any
location: any;
}
const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, isSignedIn, location, ...rest } = props;
return (
<Route
{...rest}
render={(routeProps) =>
isSignedIn ? (
<Component {...routeProps} />
) : (
<Redirect
to={{
pathname: '/signin',
state: { from: location }
}}
/>
)
}
/>
);
};
export default PrivateRoute;
import*as React from'React';
进口{
路线,,
重新使用
}从“反应路由器dom”;
接口PrivateRouteProps{
//tslint:禁用下一行:无任何
组成部分:任何;
伊西涅丁:布尔型;
//tslint:禁用下一行:无任何
地点:任何地点;
}
const PrivateRoute=(props:PrivateRouteProps)=>{
const{component:component,isSignedIn,location,…rest}=props;
返回(
伊西涅丁(
) : (
)
}
/>
);
};
导出默认私有路由;
错误
(105,18): Type '{ path: string; component: ConnectedComponentClass<typeof SomePage, Pick<SomePageProps, never>>; }' is not assignable to type 'Readonly<Pick<PrivateRouteProps, "location" | "component">>'.
Property 'location' is missing in type '{ path: string; component: ConnectedComponentClass<typeof SomePage, Pick<SomePageProps, never>>; }'.
(105,18):类型“{path:string;component:ConnectedComponentClass;}”不能分配给类型“Readonly”。
类型“{path:string;component:ConnectedComponentClass;}”中缺少属性“location”。
发生错误的原因是PrivateRouteProps
具有一个必需的属性location
,当您在components/Routes.tsx
中使用PrivateRoute
时,该属性未提供。我假设这个位置应该来自路由器自动传递给路由的render
函数的routeProps
,就像在原始示例中一样。修复后,会出现另一个错误:components/Routes.tsx
正在传递未在PrivateRouteProps
中声明的paths
属性。由于PrivateRoute
正在传递它不知道要Route
的任何道具,PrivateRouteProps
应该从react router
扩展RouteProps
,以便PrivateRoute
接受Route
接受的所有道具
这是两个修复后的组件/privaterout.tsx:
import * as React from 'react';
import {
Route,
Redirect,
RouteProps,
} from 'react-router-dom';
interface PrivateRouteProps extends RouteProps {
// tslint:disable-next-line:no-any
component: any;
isSignedIn: boolean;
}
const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, isSignedIn, ...rest } = props;
return (
<Route
{...rest}
render={(routeProps) =>
isSignedIn ? (
<Component {...routeProps} />
) : (
<Redirect
to={{
pathname: '/signin',
state: { from: routeProps.location }
}}
/>
)
}
/>
);
};
export default PrivateRoute;
import*as React from'React';
进口{
路线,,
重新使用
路线计划,
}从“反应路由器dom”;
接口PrivateRouteProps扩展了RouteProps{
//tslint:禁用下一行:无任何
组成部分:任何;
伊西涅丁:布尔型;
}
const PrivateRoute=(props:PrivateRouteProps)=>{
const{component:component,isSignedIn,…rest}=props;
返回(
伊西涅丁(
) : (
)
}
/>
);
};
导出默认私有路由;
我发现它非常有用,但需要它来为儿童
以及组件
工作,因此调整如下:
import * as React from 'react';
import { Route, Redirect, RouteProps } from 'react-router-dom';
import { fakeAuth } from '../api/Auth';
interface PrivateRouteProps extends RouteProps {
// tslint:disable-next-line:no-any
component?: any;
// tslint:disable-next-line:no-any
children?: any;
}
const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, children, ...rest } = props;
return (
<Route
{...rest}
render={routeProps =>
fakeAuth.isAuthenticated ? (
Component ? (
<Component {...routeProps} />
) : (
children
)
) : (
<Redirect
to={{
pathname: '/signin',
state: { from: routeProps.location },
}}
/>
)
}
/>
);
};
export default PrivateRoute;
import*as React from'React';
从“react router dom”导入{Route,Redirect,RouteProps};
从“../api/Auth”导入{fakeAuth};
接口PrivateRouteProps扩展了RouteProps{
//tslint:禁用下一行:无任何
组件?:任何;
//tslint:禁用下一行:无任何
儿童?:任何;
}
const PrivateRoute=(props:PrivateRouteProps)=>{
const{component:component,children,…rest}=props;
返回(
伪造的。是否已验证(
组件(
) : (
儿童
)
) : (
)
}
/>
);
};
导出默认私有路由;
注意:这恰巧是像原版一样使用了
fakeAuth
而不是user1283776的isSignedIn
redux的东西,但你明白了。当前的答案很有效,但我想发布我的解决方案,因为我认为它有一些优点:
- 不使用类型
覆盖属性any
组件
- 利用来支持组件和子道具,而无需重新实现现有的框架逻辑/代码
- 使用官方
文档react redux
import * as React from 'react';
import { connect, ConnectedProps } from 'react-redux';
import {
Redirect,
Route,
RouteProps,
} from 'react-router-dom';
import { AppState } from '../store';
const mapState = (state: AppState) => ({
loggedIn: state.system.loggedIn,
});
const connector = connect(
mapState,
{ }
);
type PropsFromRedux = ConnectedProps<typeof connector>;
type Props = PropsFromRedux & RouteProps & {
};
const PrivateRoute: React.FC<Props> = props => {
const { loggedIn, ...rest } = props;
return ( !loggedIn ? <Redirect to="/login/" /> :
<Route {...rest} />
);
};
export default connector(PrivateRoute);
import*as React from'React';
从'react redux'导入{connect,ConnectedProps};
进口{
重新使用
路线,,
路线计划,
}从“反应路由器dom”;
从“../store”导入{AppState};
常量映射状态=(状态:AppState)=>({
loggedIn:state.system.loggedIn,
});
常数连接器=连接(
mapState,
{ }
);
类型PropsFromRedux=已连接的PROPS;
类型Props=PropsFromRedux和RouteProps&{
};
const privaterote:React.FC=props=>{
常量{loggedIn,…rest}=props;
返回(!loggedIn?):
);
};
导出默认连接器(PrivateRoute);
我对我的子组件使用“React.ReactNode”类型,而不是任何组件。这真是太棒了!如果我可以问一个后续问题:当我通常不需要在我的其他组件中扩展PrivateRouteProps时,我为什么需要用RouteProps扩展PrivateRouteProps?在这种情况下扩展RouteProps
的目的是接受路径
属性,以便将其传递到路由
。如果您正在谈论的其他组件以与PrivateRoute相同的方式包裹路由
并传递道具,我希望它们的道具类型需要扩展路由路径
;如果这些组件没有包装Route
,则RouteProps
不相关。您好,欢迎使用StackOverflow!请考虑更新您的答案,以便更清楚和具体地说明在答案中张贴的原始代码中要修改的内容。考虑修改代码,并直接在更新的和工作的代码中,或更改的特定行的前后,以及对它们来自哪一个文件的引用。这将大大改善这个答案。
import * as React from 'react';
import { connect, ConnectedProps } from 'react-redux';
import {
Redirect,
Route,
RouteProps,
} from 'react-router-dom';
import { AppState } from '../store';
const mapState = (state: AppState) => ({
loggedIn: state.system.loggedIn,
});
const connector = connect(
mapState,
{ }
);
type PropsFromRedux = ConnectedProps<typeof connector>;
type Props = PropsFromRedux & RouteProps & {
};
const PrivateRoute: React.FC<Props> = props => {
const { loggedIn, ...rest } = props;
return ( !loggedIn ? <Redirect to="/login/" /> :
<Route {...rest} />
);
};
export default connector(PrivateRoute);