我正在使用React&Redux创建一个webapp。我有两个主要的“状态”代表-登录和注销。
我目前在Redux商店中将其表示为联合type State = LoggedIn | LoggedOut
,其中每个状态都由type
参数加以区分:
interface LoggedIn {
type: "LOGGED_IN"
username: string
}
interface LoggedOut {
type: "LOGGED_OUT"
}
[当我写mapStateToProps
时,我需要处理状态为LoggedOut
的情况,即使路由已经通过身份验证(即永远不会提供状态LoggedOut
),这意味着我做很多检查,例如:
const mapStateToProps = (state: State) => ({
username: state.type === "LOGGED_IN" ? state.username : ""
})
第二条条件路径: ""
将永远不会运行,但是编译器不知道。
我如何更好地代表这一点?我可以使用Typescript的字体系统删除它吗?
动作type
在减速器中用于区分不同的动作。通常它不会保存在状态中。
为了响应对type==="LOGGED_IN"
的操作,您在reducer中更改了状态,因此Redux(状态)知道该用户已经登录。
您的减速器和状态可以
interface UserState {
userName?: string;
isLoggedIn: boolean;
}
const initalUserState: UserState = {
isLoggedIn: false,
}
type KnownActions = LoggedIn | LoggedOut;
const reducer: Reducer<UserState, KnownActions> = (state = initalUserState, action) => {
switch(action.type) { // Here is type comes into play
case 'LOGGED_IN':
return { ...state, isLoggedIn: true, userName: action.userName }
case 'LOGGED_OUT':
return { ...state, isLoggedIn: false, userName: undefined }
default:
return state;
}
}
[如果您使用的是React路由器,则可以创建专用路由,该路由将仅显示登录用户的数据。例如
import { Redirect, Route, RouteProps, RouteComponentProps } from 'react-router-dom'
interface PrivateRouteOwnProps {
Render: ((props: RouteComponentProps<any>) => React.ReactNode)
}
interface PrivateRouteStateProps {
isLoggedIn: boolean;
}
type PrivateRouteProps = PrivateRouteOwnProps & PrivateRouteStateProps & RouteProps
const PrivateRoute: FC<PrivateRouteProps> = ({Render, isLoggedIn, ...rest}) => {
return <Route {...rest}
render={() => (
isLoggedIn ?
Render(props)
:
<Redirect to={"/home"}/>
)}
/>
}
export default connect((state) => ({isLoggedIn: state.isLoggedIn}))(PrivateRoute)
和用法
<Switch>
<PrivateRoute exact path='/page1' Render=(() => <Page1/>)/>
// ...
</Switch>
现在<Page1/>
仅针对已登录的用户呈现。并且在注销的情况下,用户将被重定向到“ / home”。