【问题标题】:Converting React function component to class component issue将 React 函数组件转换为类组件问题
【发布时间】:2017-09-27 11:31:21
【问题描述】:

我有以下 react 功能组件来帮助支持使用 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 参数,但我不确定如何拉...rest。我是 JSX 和 ES6 的新手,因此非常感谢任何帮助或指导。

【问题讨论】:

  • 你能用这个功能组件展示代码吗?

标签: javascript reactjs react-router jsx


【解决方案1】:

函数组件是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}/>
       );
    }
}

【讨论】:

  • 谢谢。这很有帮助。
  • 我不明白的是const {component: Component, ...rest} = this.props;。这是做什么的,就像一个反转的变量?
  • @Mr.熊:我是destructuring assignment
【解决方案2】:

通过扩展 Route 组件实现了一个不错的干净重构:

class PrivateRoute extends Route {

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

如果你使用它,你必须将你的&lt;PrivateRoute/&gt;s 包裹在一个&lt;Switch/&gt; 中,如下所示。否则,您将有重复的重定向,页面将无法加载。

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

【讨论】:

    【解决方案3】:

    @Sulthans 的回答是正确的,直接回答了您的问题。但我想用不同的方式提出建议。

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

    如果您使用最新的反应,我想建议继续使用功能组件并使用提供的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。

    【讨论】:

      【解决方案4】:

      对于您的情况,useEffect 挂钩将是最佳选择。

      你可以简单地给你的组件添加使用效果钩子

      const PrivateRoute = ({ component: Component, ...rest }) => {
      
      useEffect(()=>{
        // your logic for componentDidMount here
      }, []);
      
      return (
        <Route {...rest} render={props => (
          isAuthenticated() ? ( 
              <Component {...props}/>
          ) : (
              <Redirect to={{
                  pathname: '/login', 
                  state: {from: props.location }
              }}/>
          )
        )}/>
      )
      }
      

      【讨论】:

        猜你喜欢
        • 2018-02-17
        • 2021-11-24
        • 2022-01-17
        • 2020-01-02
        • 2020-02-01
        • 1970-01-01
        • 2021-12-10
        相关资源
        最近更新 更多