在 HOC React 中使用 React.createElement 避免错误 "Element type is invalid"

Avoid error "Element type is invalid" with React.createElement in HOC React

我想实现 PrivateRoute HOC,它将检查用户是否登录然后呈现相应的组件,否则重定向到登录页面。

这是 PrivateRoute HOC:

import React from 'react';
import { Route, Redirect } from 'react-router-dom';

const PrivateRoute = ({ component, ...rest }) => (
    <Route {...rest} render={(props) => (
        sessionStorage.getItem('userToken') ? (
            React.createElement(component, props)
        ) : (
                <Redirect to={{
                    pathname: '/login',
                }} />
            )
    )} />
);

export default PrivateRoute;

我是这样使用的:

import PrivateRoute from './components/HOC/PrivateRoute';

...

render() {
    if (this.props.hasError) return <h1>Sorry, something went wrong...</h1>;

    if (this.props.isLoading) return <h1>Loading...</h1>;

    return (
      <div className="App">
        <Switch>
          <PrivateRoute exact path="/" component={<Home /> } />
          <Route exact path="/login" render={props => <Login {...props} />} />
          <Route exact path="/registration" render={props => <Registration {...props} />} />
          <PrivateRoute exact path="/account" component={<Account />} />
        </Switch>
      </div>
    );
  }

但是报错:

我找到了一个 GitHub thread,在那里我找到了为什么会这样的可能答案,但我不知道如何为我的案例实施该答案:

我尝试了一些实验方法来实现这一点,但一切都失败了。

React.createElement 在调用 .

之前接受类型或 React 组件
React.createElement(
  type,
  [props],
  [...children]
)

The type argument can be either a tag name string (such as 'div' or 'span'), a React component type (a class or a function), or a React fragment type.


const Component = () => <>Hello</>;

// Good
React.createElement(Component)
React.createElement("div")

// Bad
React.createElement(<div/>)

在你的情况下,你使用的是“坏”版本。

您应该使用 cloneElement 或使用包装器修复它:

// Good
React.cloneElement(<Component />)

// Or make a wrapper
React.createElement(() => <Component />));

最后:

// Change to clone
React.cloneElement(component, props)

// **OR** make a wrapper
<PrivateRoute exact path="/" component={() => <Home />} />