React.createElement:type无效 - 期望一个字符串

Joe*_*dee 66 reactjs react-router react-hot-loader

试图让react-router(v4.0.0)和react-hot-loader(3.0.0-beta.6)很好地播放,但是在浏览器控制台中得到以下错误:

警告:React.createElement:type无效 - 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但得到:undefined.您可能忘记从其定义的文件中导出组件.

index.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() );
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 91

大多数情况下,这是因为您没有正确导出/导入.

常见错误:

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

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

// no "default" export, should be  export default class LeComponent
Run Code Online (Sandbox Code Playgroud)

有几种方法可能是错误的,但这种错误是由于每次都有60%的时间导入/导出错误.

编辑

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

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

遗憾的是,没有堆栈跟踪的唯一方法是手动删除每个模块/子模块,直到你不再得到错误,然后按照你的方式回到堆栈.

编辑2

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

  • 遇到了 ```import { Select } from 'react-select';``` 的问题,并将其更改为 ```import Select from 'react-select';``` (3认同)
  • 你是_sure_ index路由实际上是RR4的一部分吗?(我很确定不是) (2认同)

Ign*_*rew 9

试试这个

npm i react-router-dom@next
Run Code Online (Sandbox Code Playgroud)

在你的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;
Run Code Online (Sandbox Code Playgroud)


onm*_*133 9

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

就我而言,我通过更改从

import Provider from 'react-redux'
Run Code Online (Sandbox Code Playgroud)

import { Provider } from 'react-redux'
Run Code Online (Sandbox Code Playgroud)


lif*_*foo 8

组件数组

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

const checkoutSteps = [Address, Shipment, Payment]

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

  const ToRender = checkoutSteps[step]

  return (
    <ToRender />
  )
}
Run Code Online (Sandbox Code Playgroud)

这不一定是坏代码,但是如果您使用错误的索引调用它(例如-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
Run Code Online (Sandbox Code Playgroud)

合理的解决方案

您应该使用更明确的方法保护自己和您的同事免受这些难以调试的代码的影响,避免使用幻数并使用 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
Run Code Online (Sandbox Code Playgroud)

您的代码将如下所示:

// 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)
Run Code Online (Sandbox Code Playgroud)

这种方法的好处

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


小智 7

我也得到了这个错误.

我用的是:

import BrowserRouter from 'react-router-dom';

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

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

  • 反之亦然 - 我使用的是 `import {AppLoading} from 'expo-app-loading'` 而不是 `import AppLoading from 'expo-app-loading'` (4认同)

小智 6

循环依赖也是造成这种情况的原因之一。[一般来说]


Lit*_*ain 5

当我将 css 文件添加到与组件文件相同的文件夹时,我遇到了这个问题。

我的进口声明是:

import MyComponent from '../MyComponent'
Run Code Online (Sandbox Code Playgroud)

当只有一个文件 MyComponent.jsx 时,这很好。(我在示例中看到了这种格式并尝试了一下,然后忘记了我已经这样做了)

当我将 MyComponent.scss 添加到同一文件夹时,导入失败。也许 JavaScript 加载了 .scss 文件,所以没有错误。

我的结论是:即使只有一个文件,也始终指定文件扩展名,以防以后添加另一个文件。