如何将此React组件重写为纯函数并使用React Router获得错误/无警告实现?

时间:2018-02-23 13:47:12

标签: reactjs react-router

根据我的eslint错误建议,我一直在努力将这个反应组件重写为纯函数。我的目标是让它与反应路由器一起工作,而不会发出警告/错误。

这是类组件:

class PrivateRouteContainer extends React.Component {
  render() {
    const {
      isAuthenticated,
      component: Component,
      ...props
    } = this.props

    return (
      <Route
        {...props}
        render={props =>
          isAuthenticated
            ? <Component {...props} />
            : (
            <Redirect to={{
              pathname: '/login',
              state: { from: props.location }
            }} />
          )
        }
      />
    )
  }
}

来源:https://github.com/ReactTraining/react-router/blob/master/packages/react-router-redux/examples/AuthExample.js

这是我的eslint错误: Pure Function eslint error

这是我的尝试:

const PrivateRouteContainer = (props) => {
  const {
    isAuthenticated,
    isLoggingIn,
  } = props;

  return (
    <Route
      {...props}
      render={() =>
        (isAuthenticated || isLoggingIn
          ? <Component {...props} />
          : (
            <Redirect to={{
            pathname: '/login',
            state: { from: props.location },
          }}
            />
        ))
      }
    />
  );
};

这似乎不起作用,因为我收到错误: 警告:您不应该使用和使用相同的路线;将被忽略

如果有帮助,以下是我的路线定义:

import React from 'react';
import PropTypes from 'prop-types';
import { Route, Switch } from 'react-router';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
import { ConnectedRouter } from 'react-router-redux';

import PrivateRoute from './PrivateRoute';

import Login from '../containers/LoginPage';
import Home from '../containers/HomePage';
import List from '../containers/ListPage';
import Edit from '../containers/EditPage';

import { logout } from '../redux/auth/oauth/actions';

const ConnectedSwitch = connect(state => ({ location: state.routerReducer.location }))(Switch);

const mapStateToProps = state => ({
  isLoggingIn: state.authReducer.isLoggingIn,
  isAuthenticated: state.authReducer.isAuthenticated,
  error: state.authReducer.error,
});

const Logout = connect(mapStateToProps)(({ dispatch }) => {
  dispatch(logout());
  return <Redirect to="/" />;
});

const Routes = props =>
  (
    <ConnectedRouter history={props.history}>
      <ConnectedSwitch>
        <Route path="/" exact component={connect(mapStateToProps)(Home)} />
        <PrivateRoute path="/list" exact component={List} />
        <PrivateRoute path="/edit" component={Edit} />
        <Route path="/login" exact component={connect(mapStateToProps)(Login)} />
        <Route path="/logout" exact component={Logout} />
      </ConnectedSwitch>
    </ConnectedRouter>
  );
Routes.propTypes = {
  history: PropTypes.shape({}).isRequired,
};


export default connect(mapStateToProps)(Routes);

4 个答案:

答案 0 :(得分:0)

这只是一个错字,因为我认为你理解&#34;这&#34;没有在无状态组件中定义:

const {
    isAuthenticated,
    isLoggingIn,
} = props; // <-- remove this. here

答案 1 :(得分:0)

const PrivateRouteContainer = (props) => (
  <Route
    {...props}
    render={() =>
      (props.isAuthenticated || props.isLoggingIn
        ? <Component {...props} />
        : (
          <Redirect to={{
            pathname: '/login',
            state: { from: props.location },
          }}
          />
        ))
    }
  />
)

答案 2 :(得分:0)

您是否考虑过创建一个utils文件,例如auth.js,而不是将身份验证作为道具传递?如果用户经过验证,该文件很容易返回?

如果我们在组件处置中纠缠认证条件,我们将添加一个我们将不得不关心的附加层,这需要关心父组件的生命周期以及它如何评估认证。这也意味着你要转移到<Route />组件,它不关心或不需要关心的一些道具,这也可能有问题

为了使事情更清楚,还可以尝试使用对象解构属性,而不是在组件内部声明const,以及rest操作符。仅传递路由需要的路由,以及<Component />,仅传递组件需要的路径。这可能会导致错误,

最终结果是这样的:

import { isAuthenticated } from 'utils/auth';

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    isAuthenticated() ? (
      <Component {...props} />
    ) : (
      <Redirect to={{ pathname: '/login' }} />
    )
 )}/>
);

答案 3 :(得分:0)

我不确定这是否是最佳方法,但它似乎正在起作用......

import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Route } from 'react-router';
import { Redirect } from 'react-router-dom';

const RedirectToLogin = () => (
  <Redirect to={{ pathname: '/login' }} />
);

const PrivateRouteContainer = props => (
  <Route
    {...props}
    component={props.isAuthenticated || props.isLoggingIn ?
      props.component :
      RedirectToLogin}
  />
);

PrivateRouteContainer.propTypes = {
  isAuthenticated: PropTypes.bool.isRequired,
  isLoggingIn: PropTypes.bool.isRequired,
  component: PropTypes.func.isRequired,
};

const PrivateRoute = connect(state => ({
  isAuthenticated: state.authReducer.isAuthenticated,
  isLoggingIn: state.authReducer.isLoggingIn,
}))(PrivateRouteContainer);

export default PrivateRoute;