0

所以我最近一直在阅读 HOC,并决定在我的应用程序中使用它们来将授权逻辑传递给子组件。

我正在尝试<Route />通过 HOC 呈现组件,但它记录了错误:

未捕获的错误:AuthRoute(...):必须返回有效的 React 元素(或 null)。您可能返回了未定义、数组或其他一些无效对象。

这是 HOC 的代码:

const AuthRoute = ({ component: Component }) => {
  class AuthComponent extends Component {
    // Authorisation logic here
    render() {
      return (
          <Route render={props => <Component {...props}/>} />
      )
    }
  }
  return AuthComponent;
};

然后我使用这个 HOC 作为<Route />组件的别名,如下所示:

<BrowserRouter>
  <AuthRoute path="/account" component={PrivateComponent} />
</BrowserRouter>

编辑:

但这种方法效果很好:

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

<BrowserRouter>
  <AuthRoute path="/account" component={PrivateComponent} />
</BrowserRouter>
4

4 回答 4

1

在第一种情况下,您将返回一个类实例

const AuthRoute = ({ component: Component }) => {
  class AuthComponent extends Component {         
    // Authorisation logic here
    render() {
      return (
          <Route render={props => <Component {...props}/>} />
      )
    }
  }
  return AuthComponent;  // returning the class object here and not an instance 
};

所以如果你想使用它,你需要写

<BrowserRouter>
  <Route path="/account" component={AuthRoute(PrivateComponent)} />
</BrowserRouter>

类对象在哪里AuthRoute(PrivateComponent),Route 在内部创建一个实例

然而在第二种情况下,它不是一个 HOC,而是一个返回有效 React 元素的功能组件,

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

因此

使用<AuthRoute path="/account" component={PrivateComponent} />,您调用了一个组件实例,其中 propspathcomponent由功能组件接收。

于 2017-12-09T05:44:33.960 回答
1

您需要审查您的架构。确实,您的方法与 HOC 模式完全矛盾。您可能需要执行以下操作:

<BrowserRouter>
  <Route path="/account" component={AuthRoute(PrivateComponent)} />
</BrowserRouter>

如果您同意这种调用 HOC 的设计,那么 HOC 实现将是:

const AuthRoute = (Composed) => {
  class AuthComponent extends React.Component {
    // Authorisation logic here
    componentWillMount() {
       if (!checkAuth()) {
         this.props.history.push({pathname: '/', state: { from: this.props.location }});
       }
    }

    render() {
      return (
          <Composed {...this.props} />
      )
    }
  }
  return AuthComponent;
};
于 2017-12-09T03:53:49.373 回答
0

我对你写的语法不是很熟悉。却发现了一件事。您的参数是组件,但在您内部使用的是未定义的组件

于 2017-12-09T04:01:35.387 回答
0

它应该是 :

const AuthRoute = (Component ) => { // <-- Component which refers to PrivateComponent
  class AuthComponent extends React.Component {  // <-- React.Component
     ....       

并不是 :

const AuthRoute = ({ component: Component }) => {

    class AuthComponent extends Component { 
      ...

另请查看我的其他答案以获得优雅的 HOC 。

于 2017-12-09T04:02:47.363 回答