我在使用 React + Redux 的私人页面 / public 页面身份验证支持方面遇到了初期问题

I am having teething problems with React + Redux for private page / public page authentication support

我已经阅读了一段时间的 React,了解了一些概念,我对 SAP UI5 和 Knockoutjs 也相当熟悉。我在VS2019中开始了一个新的React + Redux模板,这个例子有天气预报和反例。

在我真正开始我的应用程序之前,我想解决身份验证方面的问题——只需要是一个假登录。我按照柜台商店中的示例添加了一个身份验证会话存储,使用身份验证,我添加了登录和注销控制器,所有这些都有效。

到目前为止,我的登录组件如下所示:

import * as React from "react";
import { connect } from "react-redux";
import { RouteComponentProps } from 'react-router';
import { ApplicationState } from '../store';
import * as AuthSession from '../store/AuthSession';

type AuthProps =
    AuthSession.AuthState &
    typeof AuthSession.actionCreators &
    RouteComponentProps<{}>;


class Login extends React.PureComponent<AuthProps> {
    public render() {
        return (
            <React.Fragment>
                <h1>Login</h1>

                <p aria-live="polite">Current IsAuthenticated= <strong>{String(this.props.IsAuthenticated)}</strong></p>
                <p aria-live="polite">Current uuid= <strong>{this.props.uuid}</strong></p>

                <button type="button"
                    className="btn btn-primary btn-lg"
                    onClick={() => { this.props.auth(); }}>
                    Auth
                </button>

            </React.Fragment>
        );
    }
};

export default connect(
    (state: ApplicationState) => state.auth,
    AuthSession.actionCreators
)(Login);

我也一直在关注与创建 LoggedInRoute 和 LoggedOutRoute 组件相关的博客,以引入和引出网站的各个方面。该博客使用箭头函数而不是 类 但是我无法理解这一点,所以我开始了自己的旅程。除了我的组件标签的属性(道具)之外,我在从 redux 存储传递我的状态时确实遇到了问题。到目前为止,我的努力是这样的:

import * as React from "react";
import { connect } from "react-redux";
import { Route } from "react-router-dom";
import { RouteComponentProps } from 'react-router';
import { ApplicationState } from '../store';
import * as AuthSession from '../store/AuthSession';

type ParamProps = {
    exact?: boolean;
    path: string;
    component: React.ComponentType<any>;
    otherProps: any
};

type ComponentProps =
    AuthSession.AuthState &
    typeof AuthSession.actionCreators &
    RouteComponentProps<{}> &
    ParamProps;


class LoggedInRoute extends React.PureComponent<ComponentProps> {
    public render() {
        if (this.props.IsAuthenticated === true) {
            return (
                <React.Fragment>
                    <p aria-live="polite">Current IsAuthenticated= <strong>{String(this.props.IsAuthenticated)}</strong></p>
                    <p aria-live="polite">Current uuid= <strong>{this.props.uuid}</strong></p>

                    <Route
                        render={otherProps => (
                            <>
                                <React.Component {...otherProps} />
                            </>
                        )}
                    />
                </React.Fragment>
            );
        } else {
            return null;
        }
    }
};

export default connect(
    (state: ApplicationState, ownProps: ParamProps) => {
        return { ...state.auth, ...ownProps }
    },
    AuthSession.actionCreators,
)(LoggedInRoute);

这给了我一个错误:

TypeScript error in /src/App.tsx(21,10): Type '{ path: string; component: ConnectedComponentClass<typeof Logout, Pick<AuthProps, "location" | "history" | "match" | "staticContext">>; }' is missing the following properties from type 'Readonly & ParamProps>': location, history, match, uuid, and 2 more. TS2740 19 | 20 | > 21 | | ^ 22 | 23 | );

我可以在各种文档中清楚地看到,connect 旨在通过将自己的属性和 redux 状态注入子控件道具来执行我想要的操作,但显然这对我不起作用。

我如何指定连接,以便我可以传递 redux 状态,并且还可以通过特定的命名属性以及其余属性来实现这一技巧? - 即 {stateprops, component, ...otherProps}

一个很长的问题,但我相信这对大多数 React 程序员来说很简单。

谢谢

我仔细看了看它,让它工作了:

import * as React from "react";
import { connect } from "react-redux";
import { Route } from "react-router-dom";
import { RouteComponentProps } from 'react-router';
import { ApplicationState } from '../store';
import * as AuthSession from '../store/AuthSession';

type ParamProps = {
    exact?: boolean;
    path: string;
    component: React.ComponentType<any>;
    otherProps?: any
};

type ComponentProps =
    AuthSession.AuthState &
    typeof AuthSession.actionCreators &
    RouteComponentProps<{}> &
    ParamProps;


class LoggedInRoute extends React.PureComponent<ComponentProps> {
    public render() {
        var props = this.props;
        var Component = props.component;
        if (this.props.IsAuthenticated === true) {
            return (
                <React.Fragment>
                    <Route path={props.path}
                        render={otherProps => (
                            <>
                                <Component component={props.component} {...otherProps} />
                            </>
                        )}
                    />
                </React.Fragment>
            );
        } else {
            return (false);
;
        }
    }
};

export default connect(
    (state: ApplicationState, ownProps: any) => {
        const { component, path, ...rest } = ownProps;
        let op = {} as ParamProps;
        op.component = component;
        op.path = path;
        op.otherProps = rest;
        let st = { ...state.auth, ...op } as ComponentProps;
        return st;
        },
    AuthSession.actionCreators,
)(LoggedInRoute);

需要进行两项更改:

1) 是的,您可以在连接状态映射中编写您的道具。您只需 return 您在类型中指定的特定字段(如预期的那样)。然而,注入的 "ownProps" 属性 不包含您指定的类型,您必须构建正确的类型。

2) 当我完成这个时,React 似乎不知道如何渲染传入的组件。事实证明 JSX/TSX 将渲染保存在变量中的组件,如果该变量以大写字母开头。所以我将 "component" 属性 分配给了 "Component" 变量。现在我明白了,我真的很喜欢这个功能。

:)