簡體   English   中英

將 React function 組件轉換為 class 組件問題

[英]Converting React function component to class component issue

我有以下 React 功能組件來幫助支持 react-router 所需的身份驗證路由。

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

我需要將其從功能組件轉換為 class 組件,以便我可以利用 React.Component 的 componentDidMount 方法。 不幸的是,我無法弄清楚如何遷移它。 如果我按原樣使用它,我需要復制組件和...rest 參數,但我不確定該怎么做。 我想我可以用 this.props.component 獲取 Component 參數,但我不確定如何拉...rest。 我是 JSX 和 ES6 的新手,所以非常感謝任何幫助或指導。

功能組件是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}/>
       );
    }
}

通過擴展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>

@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 團隊現在提倡使用函數組件。 推薦閱讀逐步采用策略

對於您的情況,useEffect hook 將是最佳選擇。

您可以簡單地將使用效果掛鈎添加到您的組件

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 }
        }}/>
    )
  )}/>
)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM