将React函数组件转换为类组件问题

时间:2017-04-29 12:13:55

标签: javascript reactjs react-router jsx

我有以下反应功能组件来帮助支持使用react-router的身份验证所需的路由。

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

我需要将它从功能组件转换为类组件,以便我可以利用React.Component的componentDidMount方法。不幸的是,我无法弄清楚如何迁移它。如果我按原样使用它,我需要复制Component和... rest参数,但我不知道该怎么做。我想我可以使用this.props.component获取Component参数,但我不确定如何拉...休息。我是JSX和ES6的新手,所以我们非常感谢任何帮助或指导。

3 个答案:

答案 0 :(得分:18)

真的没有什么困难。功能组件是render函数,因此:

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

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

或者,写得更具可读性:

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

       const renderRoute = props => {
           if (isAuthenticated()) {
              return (
                  <Component {...props} />
              );
           }

           const to = {
               pathname: '/login', 
               state: {from: props.location}
           };

           return (
               <Redirect to={to} />
           );
       }

       return (
           <Route {...rest} render={renderRoute}/>
       );
    }
}

答案 1 :(得分:0)

通过扩展Route组件,可以很好地进行重构:

class PrivateRoute extends Route {

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

如果使用此方法,则必须将<PrivateRoute/>s包裹在<Switch/>中,如下所示。否则,您将具有重复的重定向,并且页面将无法加载。

<Router>
    <Navbar/>
    <SideDrawer/>
    <Switch>
        <Route              path="/tokens"   component={Login}/>
        <PrivateRoute exact path="/"         component={ExampleComponent}/>
        <PrivateRoute       path="/users"    component={Users}/>
        <PrivateRoute       path="/software" component={Software}/>
    </Switch>                   
</Router>

答案 2 :(得分:0)

@Sulthans 的回答是正确的,并且直接回答了您的问题。但我想以不同的方式给出一个建议。

根据您的问题,您的要求类似于在功能组件中使用生命周期挂钩,即 componentDidMount

如果您使用的是最新的 react,我建议您继续使用功能组件并使用 useEffect 实现钩子

useEffect(() => {
  console.log('mount it!');
}, []); // passing an empty array as second argument triggers the callback in useEffect only after the initial render thus replicating `componentDidMount` lifecycle behaviour

我推荐这个是因为以下原因

  • 它减少了样板
  • 它促进了可靠性
  • React 团队现在提倡使用功能组件。推荐阅读gradual adoption strategy