【问题标题】:high order component throws an invalid react element error (reactjs)高阶组件抛出无效的反应元素错误(reactjs)
【发布时间】:2018-05-23 07:58:41
【问题描述】:

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

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

未捕获的错误: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 作为 &lt;Route /&gt; 组件的别名,如下所示:

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

【问题讨论】:

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


    【解决方案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;
    };
    

    【讨论】:

    • 这看起来比较熟悉:)
    • @Abdennour 你能解释一下我的方法与我对问题所做的编辑完全矛盾吗?
    • 当然@m-ketan!我看到了您的更新,这就是为什么我也更新了答案;查看componentWillMount ? 恭喜!
    【解决方案2】:

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

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

    因此

    使用 &lt;AuthRoute path="/account" component={PrivateComponent} /&gt; ,您调用了一个组件实例,由此功能组件接收道具 pathcomponent

    【讨论】:

    • 感谢您的解释。
    • 很高兴它帮助你理解
    【解决方案3】:

    应该是:

    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。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 其实不是 undefined 而是 React.Component
      猜你喜欢
      • 2021-10-20
      • 1970-01-01
      • 2016-02-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 2017-10-18
      • 2022-11-24
      相关资源
      最近更新 更多