高阶组件抛出无效的反应元素错误(reactjs)

时间:2017-12-09 03:37:32

标签: reactjs react-router higher-order-components

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

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

  

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

以下是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 个答案:

答案 0 :(得分: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;
};

答案 1 :(得分: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} />,您调用了一个组件实例,功能组件会收到道具pathcomponent

答案 2 :(得分:0)

我对你写的语法不太熟悉。但发现了一件事。您的参数是组件,但在您使用的组件中,在此上下文中未定义

答案 3 :(得分:0)

应该是:

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

而不是:

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

    class AuthComponent extends Component { 
      ...

同时查看my other answer以获得优雅的HOC。