表示Redux和Typescript中的“已登录”和“已退出”,以避免对mapStateToProps进行过多检查

问题描述 投票:1回答:1

我正在使用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的字体系统删除它吗?

reactjs typescript redux store
1个回答
0
投票
  1. 动作type在减速器中用于区分不同的动作。通常它不会保存在状态中。

  2. 为了响应对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”。

© www.soinside.com 2019 - 2024. All rights reserved.