web-dev-qa-db-ja.com

React関数コンポーネントからクラスコンポーネントへの変換の問題

次の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パラメーターを取得できると思いますが、...レストをプルする方法がわかりません。私はJSXとES6を初めて使用するので、ヘルプやガイダンスをいただければ幸いです。

13
Chris Dellinger

本当に難しいことは何もありません。機能コンポーネントは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}/>
       );
    }
}
21
Sulthan

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>
1
Cameron Hudson