React.createElement:类型无效-预期为字符串


99

试图使react-router(v4.0.0)和react-hot-loader(3.0.0-beta.6)正常播放,但是在浏览器控制台中出现以下错误:

警告:React.createElement:类型无效-预期为字符串(对于内置组件)或类/函数(对于复合组件),但得到:未定义。您可能忘记了从定义文件中导出组件。

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() );

route.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;

如果您使用react-router-config,请确保使用component属性而不是render,因为该软件包不支持更高版本。在GitHub上查看更多
totymedli '18

Answers:


129

在大多数情况下,这是由于错误的导出/导入引起的。

常见错误:

// 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%的导入/导出不匹配。

编辑

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

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

遗憾的是,没有堆栈跟踪的唯一方法是手动删除每个模块/子模块,直到不再收到错误,然后再按照自己的方式备份堆栈。

编辑2

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


看过指向route.js第12行的跟踪。那行是<IndexRoute component={Products} />
JoeTidee

2
确定索引路由实际上是RR4的一部分吗?(我敢肯定不是)
克里斯(Chris

那就是问题-谢谢!我已恢复为v3.0.0
JoeTidee

很好,好东西。随时将其标记为已接受的答案,因为它将帮助未来的读者知道如何解决类似的问题
克里斯(Chris

1
@PriyaRanjanSingh仅凭一点评论是不可能的。您可以发布一个包含详细信息的新问题吗?
克里斯,


11

试试这个

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;

5

您需要注意named exportdefault export。请参阅何时应将花括号用于ES6导入?

就我而言,我通过更改

import Provider from 'react-redux'

import { Provider } from 'react-redux'

我已将问题缩小到此提供者。但是,我已经在使用{Provider}表示法。
杰森G

4

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

我的进口声明是:

import MyComponent from '../MyComponent'

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

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

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


3

对于未来的Google员工:

我对这个问题的解决办法是升级reactreact-dom对新公共管理的最新版本。显然我正在导入使用新片段语法的Component,并且在我的旧版React中已将其破坏。


2

当我在渲染/返回语句中引用错误时,就发生了这个问题。(指向不存在的类)。还要检查您的退货声明代码是否有错误的引用。


2

在大多数情况下,这表明导入/导出错误。但是要小心,不仅要确保堆栈跟踪中的引用文件本身已正确导出,而且还请确保此文件正确地导入了其他组件。就我而言,错误是这样的:

import React from 'react';

// Note the .css at the end, this is the cause of the error!
import SeeminglyUnimportantComponent from './SeeminglyUnimportantComponent.css';

const component = (props) => (            
  <div>
    <SeeminglyUnimportantComponent />
    {/* ... component code here */}
  </div>    
);

export default component;


感谢您的评论!自从更新了一些软件包以来,我就遇到了这个问题,并且我一直在浏览所有这些注释,而这些代码中都没有问题。但这就是问题文件导入了其他导致错误的文件!
黛安·卡普兰 Diane Kaplan)

2

我认为解决此错误时最重要的事情是,当您尝试实例化一个不存在的组件时,它就会显现出来。该组件不必导入。就我而言,我将组件作为属性传递。在进行一些重构后,我忘记更新其中一个调用以正确传递组件。不幸的是,由于JS不是静态类型的,所以没有捕获到我的错误,并且花了一些时间才能弄清楚发生了什么。

要解决此错误,请在渲染组件之前检查组件,以确保它是您期望的组件类型。


“当您尝试实例化不存在的组件时,它就会显示出来” –这就是发生在我身上的事情。该组件已正确导入/导出,但我将其作为道具通过了react-router中的授权路由,却忘记将更render={props => <Component {...props} />}改为component={Component}
displacedtexan

2

我错过了一个React Fragment


function Bar({ children }) {

  return (
    <div>
     {children}
    </div>
  );
}

function Foo() {
  return (
    <Bar>
      <Baz/>
      <Qux/>
    </Bar>
  );
}

上面的代码抛出上面的错误。但这可以解决:

<Bar>
  <>
    <Baz/>
    <Qux/>
  </>
</Bar>

当我添加ReactCollapsingTable(yarn add react-collapsing-table)时发生了。我设法此警告(即导致在水合错误)之间交替和“没有定义窗口”一个被检测内部编译反应压扁表模块......连包装与<div>...</div>于事无补了
superk

最终,我从头开始重新编译了整个项目(而不是热重载),问题再次发生。在这里找到解决方案:stackoverflow.com/a/43969990/2821963(而不是import module from 'module-name'使用require(module-name).default
superk

2

组件阵列

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

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用于...)
  • 错误是明确的
  • 对您的同行没有头痛:)

1

我缺少的是我正在使用的

import { Router, Route, browserHistory, IndexRoute } from 'react-router';

相反或正确的答案应该是:

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

当然,您需要添加npm包react-router-dom

npm install react-router-dom@next --save


0

就我而言,创建组件和渲染的顺序很重要。我在创建组件之前就对其进行了渲染。最好的方法是先创建子组件,再创建父组件,然后渲染父组件。更改订单对我来说解决了这个问题。


0

就我而言,我只需要从升级到react-router-redux即可react-router-redux@next。我假设它一定是某种兼容性问题。


0

简而言之,以下情况正在发生:

render() {
    return (
        <MyComponent /> // MyComponent is undefined.
    );
}

它可能不一定与某些不正确的导入或导出有关:

render() {
    // MyComponent may be undefined here, for example.
    const MyComponent = this.wizards[this.currentStep];

    return (
        <MyComponent />
    );
}

0

如果在测试组件时遇到此错误,请确保每个子组件在单独运行时都能正确呈现,如果您的一个子组件依赖于外部资源进行渲染,请尝试使用jest或任何其他模拟lib对其进行模拟:

范例:

jest.mock('pathToChildComponent', () => 'mock-child-component')

0

就我而言,尝试使用ContextApi时发生了错误。我误用了:

const MyContext = () => createContext()

但是它应该被定义为:

const MyContext = createContext()

我将其张贴在此处,以便将来因此类愚蠢错误而卡住的访客将有助于避免数小时的头痛,因为这不是由错误的导入/导出引起的。



0

这是一些必须调试的错误。正如许多次所说的那样,不正确的导入/导出会导致此错误,但是令人惊讶的是,我从一个小错误中得到了此错误。react-router-dom authentication setup是是下面的:

错误设置:

const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route
        {...rest}
        render={(props) => (token ? <Component {...props} /> : <Redirect to={{ pathname: "/login" }} />)}
    />
);

正确的设置:

const PrivateRoute = ({ component: Component, token, ...rest }) => (
    <Route
        {...rest}
        render={(props) => (token ? <Component {...props} /> : <Redirect to={{ pathname: "/login" }} />)}
    />
);

唯一的区别是我是解构tokenPrivateRoute component。令牌从得到的方式localstorage是这样const token = localStorage.getItem("authUser");,所以如果它不存在,我知道该用户未通过身份验证。这也会导致该错误。


0

确实很简单。我开始编码React时遇到了这个问题,问题几乎总是因为导入而引起的:

import React, { memo } from 'react';

您可以使用此方法进行解构,因为react lib具有作为备注的属性,但是您不能对此类内容进行解构

import { user } from 'assets/images/icons/Profile.svg';

因为它不是对象。

希望能帮助到你!


0

反应片段

为我解决了这个问题

错误代码:

 return (
            <section className={classes.itemForm}>
             <Card>
             </Card> 
            </section>
      );

固定

 return (
      <React.Fragment>
        <section className={classes.itemForm}>
         <Card>
         </Card> 
        </section>
      </React.Fragment>
  );

0

这不一定是与导入/导出有关的直接问题。就我而言,我在父元素内渲染了一个子元素,并且该子元素具有jsx元素/标记,该标记已使用但未导入。我导入了它,然后使用它解决了问题。因此问题出在子元素内部的jsx元素中,而不是子元素本身的导出中。


-1

我只花了30分钟来尝试解决这个BASIC基本问题。

我的问题是我正在导入反应本机元素

例如 import React, { Text, Image, Component } from 'react';

并尝试使用它们,这导致我收到此错误。

有一次,我从切换<Text><p><Image><img>一切都按预期。


-1

我收到此错误,我的情况没有一个答案,它可能会帮助某人进行谷歌搜索:

我定义了一个Proptype错误:

ids: PropTypes.array(PropTypes.string)

它应该是:

ids: PropTypes.arrayOf(PropTypes.string)

VSCode和编译错误没有给我正确的提示。


-2

编辑

您正在使过程复杂化。只要这样做:

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

ReactDom.render(<routes />, document.getElementById('root'));

route.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;

您确定问题出在这里吗?而不是来自页面本身吗?
约翰·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.