React.createElement:类型无效——需要一个字符串

IT技术 reactjs react-router react-hot-loader
2021-04-06 00:51:32

试图让 react-router (v4.0.0) 和 react-hot-loader (3.0.0-beta.6) 运行良好,但在浏览器控制台中出现以下错误:

Warning: React.createElement: type is invalid -- expected a string
(for built-in components) or a class/function (for composite
components) but got: undefined. You likely forgot to export your
component from the file it's defined in.

索引.js:

import React from 'react';
import ReactDom from 'react-dom';
import routes from './routes.js';
require('jquery');
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import './css/main.css';

const renderApp = (appRoutes) => {
    ReactDom.render(appRoutes, document.getElementById('root'));
};

renderApp( routes() );

路线.js:

import React from 'react';
import { AppContainer } from 'react-hot-loader';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import store from './store/store.js';
import { Provider } from 'react-redux';
import App from './containers/App.jsx';
import Products from './containers/shop/Products.jsx';
import Basket from './containers/shop/Basket.jsx';

const routes = () => (

    <AppContainer>
        <Provider store={store}>
            <Router history={browserHistory}>
                <Route path="/" component={App}>
                    <IndexRoute component={Products} />
                    <Route path="/basket" component={Basket} />
                </Route>
            </Router>
        </Provider>
    </AppContainer>

);

export default routes;
6个回答

大多数情况下,这是由于不正确的导出/导入。

常见错误:

// File: LeComponent.js
export class LeComponent extends React.Component { ... }

// File: App.js
import LeComponent from './LeComponent';

可能的选择:

// File: LeComponent.js 
export default class LeComponent extends React.Component { ... }

// File: App.js
import LeComponent from './LeComponent';

有几种方法可能是错误的,但该错误是因为每次都有 60% 的导入/导出不匹配。

编辑

通常,您应该获得一个堆栈跟踪,指示故障发生的大致位置。这通常紧跟在您在原始问题中收到的消息之后。

如果它没有显示,则可能值得调查原因(这可能是您缺少的构建设置)。无论如何,如果它不显示,唯一的行动方针是缩小其中的导出/导入失败。

可悲的是,没有堆栈跟踪的唯一方法是手动删除每个module/子module,直到您不再收到错误为止,然后按自己的方式返回堆栈。

编辑 2

通过评论,这确实是一个导入问题,特别是导入了一个不存在的module

查看了指向 routes.js 第 12 行的跟踪。那条线是<IndexRoute component={Products} />
2021-05-25 00:51:32
很棒,好东西。随意将其标记为已接受的答案,因为它将帮助未来的读者了解如何处理类似问题
2021-05-30 00:51:32
确定索引路由实际上是 RR4 的一部分吗?(我很确定它不是)
2021-06-03 00:51:32
这就是问题所在 - 谢谢!我已经恢复到 v3.0.0
2021-06-03 00:51:32
@PriyaRanjanSingh 仅凭一点评论就无法判断。您可以发布一个包含详细信息的新问题吗?
2021-06-13 00:51:32

我也收到了这个错误。

我正在使用:

import BrowserRouter from 'react-router-dom';

修复是这样做的,而不是:

import { BrowserRouter } from 'react-router-dom';

试试这个

npm i react-router-dom@next

在你的App.js 中

import { BrowserRouter as Router, Route } from 'react-router-dom'

const Home = () => <h1>Home</h1>

const App = () =>(
  <Router>
    <Route path="/" component={Home} />
  </Router>
)

export default App;

组件数组

获取此错误的常见方法是使用components 数组,并使用位置索引从数组中选择要呈现的组件。我多次看到这样的代码:

const checkoutSteps = [Address, Shipment, Payment]

export const Checkout = ({step}) => {

  const ToRender = checkoutSteps[step]

  return (
    <ToRender />
  )
}

这不一定是坏代码,但是如果您使用错误的索引调用它(例如-1, 或者3在这种情况下),ToRender组件将是undefined,抛出React.createElement: type is invalid...错误:

<Checkout step={0} /> // <Address />
<Checkout step={1} /> // <Shipment />
<Checkout step={2} /> // <Payment />
<Checkout step={3} /> // undefined
<Checkout step={-1} /> // undefined

合理的解决方案

您应该使用更明确的方法保护自己和您的同事免受这种难以调试的代码的影响,避免使用幻数并使用 PropTypes:

const checkoutSteps = {
  address: Address,
  shipment Shipment,
  payment: Payment
}

const propTypes = {
  step: PropTypes.oneOf(['address', 'shipment', 'payment']),
}

/* TIP: easier to maintain
const propTypes = {
  step: PropTypes.oneOf(Object.keys(checkoutSteps)),
}
*/

const Checkout = ({step}) => {

  const ToRender = checkoutSteps[step]

  return (
    <ToRender />
  )
}

Checkout.propTypes = propTypes

export default Checkout

您的代码将如下所示:

// OK
<Checkout step="address" /> // <Address />
<Checkout step="shipment" /> // <Shipment />
<Checkout step="payment" /> // <Payment />

// Errors
<Checkout step="wrongstep" /> // explicit error "step must be one of..."
<Checkout step={3} /> // explicit error (same as above)
<Checkout step={myWrongVar} /> // explicit error (same as above)

这种方法的好处

  • 代码更明确,可以清楚地看到要渲染的内容
  • 你不需要记住数字和它们隐藏的含义(1是地址,2是...)
  • 错误是明确的
  • 不为你的同龄人头疼:)

你需要知道named exportdefault export请参阅何时应该使用花括号进行 ES6 导入?

就我而言,我通过更改从

import Provider from 'react-redux'

import { Provider } from 'react-redux'
我已经将我的问题缩小到这个 Provider。但是,我已经在使用 { Provider } 表示法。
2021-05-22 00:51:32