在Redux和Typescript中表示“已登录”和“已注销”,以避免对mapStateToProps进行过多检查

我正在使用React&Redux创建一个Webapp。我有两个主要的“状态”代表-登录和注销。

我目前在Redux商店中将其表示为联合体type State = LoggedIn | LoggedOut,其中每个状态都由type参数来区分:

interface LoggedIn {
    type: "LOGGED_IN"
    username: string
}


interface LoggedOut {
    type: "LOGGED_OUT"
}

当我写mapstatetoProps时,即使状态已经通过验证(即永远不会提供状态{{1),我也要处理状态为LoggedOut的情况}}),这意味着我要进行很多检查,例如:

LoggedOut

第二条条件路径const mapstatetoProps = (state: State) => ({ username: state.type === "LOGGED_IN" ? state.username : "" }) 永远不会运行,但是编译器不知道。

我该如何更好地代表这一点?我可以使用Typescript的文字系统将其删除吗?

wuyeyou0773 回答:在Redux和Typescript中表示“已登录”和“已注销”,以避免对mapStateToProps进行过多检查

  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”。

本文链接:https://www.f2er.com/2995723.html

大家都在问