将具有参数的无状态React组件转换为有状态

Vis*_*tty 4 javascript reactjs react-router react-redux

在我的React JS项目中,我正在研究PrivateRoutes.我已经完成了私有路由和使用身份验证的示例react-router-dom.

https://reacttraining.com/react-router/web/example/auth-workflow

根据这个文档,他们创建了PrivateRoute一个无状态组件.

但我的要求是将其转换为有状态的React组件,因为我想将我的PrivateRoute组件连接到redux store.

这是我的代码.

无国籍组成部分

import React from 'react';
import {Route, Redirect} from 'react-router-dom';
import {auth} from './Authentication';

const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route
      {...rest}
      render={props =>
        auth.isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Component {...props} action="login"/>
        )
      }
    />
  );

  export default PrivateRoute;
Run Code Online (Sandbox Code Playgroud)

我将此组件转换为有状态React组件.

有状态的React组件

import React from 'react';
import {Route, Redirect} from 'react-router-dom';
import {auth} from './Authentication';
import {connect} from 'react-redux';

  class PrivateRoute extends React.Component {
    render({ component: Component, ...rest }) {
      return (
        <Route
          {...rest}
          render={props =>
            this.props.customer.isAuthenticated ? (
              <Component {...props} />
            ) : (
              <Component {...props} action="login"/>
            )
          }
        />
      );
    }
  }
  export default connect(state => state)(PrivateRoute);
Run Code Online (Sandbox Code Playgroud)

在这里,我正在读取redux store中的数据,以检查用户是否已经过身份验证.

但是我将无状态组件转换为有状态的方式是不正确的.

render({ component: Component, ...rest })正确地传递了论据 吗?

将连接PrivateRoute用Redux的商店创建任何问题,props因为state=>state将映射stateprops以及...rest将有props对象吗?

不确定代码中发生了什么.

更新 AppRouter.js

import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import {TransitionGroup, CSSTransition} from 'react-transition-group';
import PrivateRoute from './PrivateRoute';

import HomePage from './../components/HomePage';
import AboutUs from './../components/AboutUs';
import ContactUs from './../components/ContactUs';
import PageNotFound from './../components/PageNotFound';
import RestaurantList from '../components/RestaurantList';
import RestaurantMenu from '../components/RestaurantMenu';
import UserDetails from '../components/UserDetails';
import OrderConfirmation from '../components/OrderConfirmation';
import CustomerAccount from '../components/CustomerAccount';
import Logout from '../components/sections/Logout';


export default () => {
    return (
        <BrowserRouter>
            <Route render={({location}) => (
                <TransitionGroup>
                    <CSSTransition key={location.key} timeout={300} classNames="fade">
                        <Switch location={location}>
                            <Route path="/" component={HomePage} exact={true}/>
                            <Route path="/about" component={AboutUs} />
                            <Route path="/contact" component={ContactUs} />
                            <Route path="/restaurants" component={RestaurantList} />
                            <Route path="/select-menu" component={RestaurantMenu} />
                            <PrivateRoute path="/user-details" component={UserDetails} />
                            <PrivateRoute path="/order-confirmation" component={OrderConfirmation} />
                            <PrivateRoute path="/my-account" component={CustomerAccount} />
                            <PrivateRoute path="/logout" component={Logout} />

                            <Route component={PageNotFound} />
                        </Switch>
                    </CSSTransition>
                </TransitionGroup>
            )} />

        </BrowserRouter>
    );
}
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 7

通常,将无状态功能组件(SFC)转换为a Component是这样的:

  1. class为它创建shell.

  2. 将SFC的正文复制到该render方法.如果SFC是箭头功能,请return根据需要添加render.

  3. propsrender方法中的任何引用更改为this.props(或仅添加const { props } = this;到顶部).SFC在其参数中接收它们的道具,但是一个组件将它们作为其构造函数的参数接收; 默认构造函数将它们保存为this.props.

    在你的情况下,它在其参数上使用解构,所以你可以this.props在解构的右边做同样的事情:

    const { component: Component, ...rest } = this.props;
    
    Run Code Online (Sandbox Code Playgroud)

而已.在您的代码,您添加参数的render功能,但它不会叫任何参数,你只改propsthis.props有点随意(包括更改auth.isAuthenticatedthis.props.customer.isAuthenticated某种原因).

所以应用1-3以上:

// #1 - the shell
class PrivateRoute extends React.Component {
  // #2 - `render`, with the body of the SFC inside
  render() {
    // #3 - destructure `this.props`
    const { component: Component, ...rest } = this.props;
    // #2 (part 2) - add `return`
    return <Route
      {...rest}
      render={props =>
        auth.isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Component {...props} action="login"/>
        )
      }
    />;
  }
}
Run Code Online (Sandbox Code Playgroud)


Vis*_*tty 0

我有两个疑问。

1)如何转换为有状态功能组件?2)连接到redux store后,props会产生问题吗?

我的第一个疑问由 提供的答案解决了T.J.Crowder

对于第二个查询,我尝试连接到,redux store并且PrivateRoute确实得到了我正在寻找的数据。

这是对我有用的代码。

import React from 'react';
import {Route, Redirect} from 'react-router-dom';
import {connect} from 'react-redux';

class PrivateRoute extends React.Component {
  render() {
    const { component: Component, ...rest } = this.props;
    const {customer} = this.props;

    return <Route
      {...rest}
      render={props =>
        customer.isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Component {...props} action="login"/>
        )
      }
    />;
  }
}

export default connect(state => state)(PrivateRoute);
Run Code Online (Sandbox Code Playgroud)

使用这段代码,我获取了来自路由的数据,以及 props 内的 redux 状态。

这是从路线获取数据 const { component: Component, ...rest } = this.props;

这是来自 redux 存储的数据。 const {customer} = this.props;