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

React.createElement: type is invalid -- expected a string

试图让 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.

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

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;

编辑

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

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

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;

大多数情况下这是由于 export/import.

不正确造成的

常见错误:

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

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

编辑

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

如果它没有显示,可能值得调查原因(它可能是您缺少的构建设置)。无论如何,如果它没有显示,唯一的行动方案是缩小 和 export/import 失败的范围。

遗憾的是,没有堆栈跟踪的唯一方法是手动删除每个 module/submodule 直到您不再收到错误,然后再返回堆栈。

编辑 2

通过评论,确实是导入问题,具体是导入了一个不存在的模块

试试这个

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;

我缺少的是我正在使用

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

我也遇到了这个错误。

我正在使用:

import BrowserRouter from 'react-router-dom';

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

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

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

我的导入语句是:

import MyComponent from '../MyComponent'

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

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

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

对于未来的 google 员工:

我对这个问题的解决方案是将 reactreact-dom 升级到 NPM 上的最新版本。显然我正在导入一个使用 new fragment syntax 的组件,它在我的旧版本 React 中被破坏了。

您需要了解 named exportdefault export。参见

就我而言,我通过从

更改来修复它
import Provider from 'react-redux'

import { Provider } from 'react-redux'

就我而言,创建组件和渲染的顺序很重要。我在创建组件之前渲染它。最好的方法是先创建子组件,再创建父组件,再渲染父组件。更改顺序为我解决了问题。

在我的例子中,我只需要从 react-router-redux 升级到 react-router-redux@next。我假设它一定是某种兼容性问题。

简而言之,不知何故发生了以下情况:

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

不一定与某些错误的导入或导出有关:

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

    return (
        <MyComponent />
    );
}

我刚刚花了 30 分钟试图解决这个 BASIC 基本问题。

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

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

试图使用它们,导致我收到此错误。

一旦我从 <Text> 切换到 <p> 并从 <Image> 切换到 <img> 一切都按预期工作。

当我在 render/return 语句中引用错误时,我遇到了这个问题。 (指向一个不存在的 class)。 还要检查您的 return 语句代码是否存在错误引用。

我遇到了这个错误,none 的回复是我的情况,这可能有助于谷歌搜索:

我定义的 Proptype 错误:

ids: PropTypes.array(PropTypes.string)

应该是:

ids: PropTypes.arrayOf(PropTypes.string)

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

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

示例:

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

大多数情况下,这表示 import/export 错误。但要注意,不仅要确保堆栈跟踪中引用的文件本身导出良好,还要确保该文件正确导入 其他组件。在我的例子中,错误是这样的:

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;

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

const MyContext = () => createContext()

但应该定义为:

const MyContext = createContext()

我将它张贴在这里是为了让以后陷入这种愚蠢错误的访问者能够避免数小时的头痛,因为这不是由不正确的 import/export.

引起的

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

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

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

我漏了一个 React Fragment:


function Bar({ children }) {

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

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

上面的代码抛出了上面的错误。但这修复了它:

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

在我的例子中,我忘记导入和导出渲染器在 index.js 文件中调用的我的(新)元素。

这是一个必须如何调试的错误。正如已经说过很多次的那样,不正确的 import/export 会导致此错误,但令人惊讶的是,我从 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" }} />)}
    />
);

唯一的区别是我在 PrivateRoute component 中解构了 token。顺便说一句,令牌是从 localstorage 中获取的,就像这样 const token = localStorage.getItem("authUser"); 所以如果它不存在,我知道用户未通过身份验证。这也可能导致该错误。

真的很简单。我在开始编写 React 代码时遇到了这个问题,问题几乎总是因为 import:

import React, { memo } from 'react';

你可以使用 destructuring this 因为 react lib 有一个 属性 作为 memo,但是你不能解构像这样的东西

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

因为它不是对象。

希望对您有所帮助!

React.Fragment

为我解决了问题

错误代码:

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

修复

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

这不一定是与 import/export 相关的直接问题。在我的例子中,我在父元素内渲染一个子元素,子元素有 jsx 元素/标签,它被使用但没有被导入。我导入它并使用它然后它解决了问题。所以问题出在子元素内部的 jsx 元素中,而不是子元素本身的导出。

组件数组

出现此错误的常见方法是使用 组件数组 ,其中 位置索引 用于 select从数组中渲染的组件。我多次看到这样的代码:

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是对于...)
  • 错误也是明确的
  • 不会让您的同龄人头疼 :)
xxxxx.prototype = {
  dxxxx: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};

您必须添加 // eslint-disable-line react/forbid-prop-types,然后才有效!

我遇到了完全相同的错误,改为执行此操作:

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

说明你的import/export不正确.

  • 勾选新增import/exports.
  • 在我的例子中,我没有必要使用大括号。当我删除这些花括号时,问题自动得到解决。
import { OverlayTrigger } from 'react-bootstrap/OverlayTrigger';
// @flow

import React from 'react';
import { styleLocal } from './styles';
import {
  View,
  Text,
  TextInput,
  Image,
} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';

export default React.forwardRef((props, ref) => {
const { onSeachClick, onChangeTextSearch , ...otherProps } = props;

  return (
        <View style={styleLocal.sectionStyle}>
        <TouchableOpacity onPress={onSeachClick}>
            <Image                              
                    source={require('../../assets/imgs/search.png')}
                    style={styleLocal.imageStyle} />
                </TouchableOpacity>
            <TextInput
                style={{ flex: 1, fontSize: 18 }}
                placeholder="Search Here"
                underlineColorAndroid="transparent"
                onChangeText={(text) => { onChangeTextSearch(text) }}
            />
        </View>
  );
});
 import IGPSSearch from '../../components/IGPSSearch';
<Search onSeachClick={onSeachClick} onChangeTextSearch= {onChangeTextSearch}> </Search>

我也遇到了这个错误。

我正在使用:

import ReactDOM from 'react-dom';

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

import {ReactDOM} from 'react-dom';

在我的例子中,我添加了与道具相同的自定义组件而不是实际道具

   import AddAddress from '../../components/Manager/AddAddress';
    
    class Add extends React.PureComponent {
      render() {
        const {
          history,
          addressFormData,
          formErrors,
          addressChange,
          addAddress,
          isDefault,
          defaultChange
        } = this.props;
    

错误:

    return (
        <AddAddress
          addressFormData={addressFormData}
          formErrors={formErrors}
          addressChange={addressChange}
          addAddress={AddAddress} // here i have used the Component name as probs in same component itself instead of prob
          isDefault={isDefault}
          defaultChange={defaultChange}
        />
      </SubPage>

解法:

return (
    <AddAddress
      addressFormData={addressFormData}
      formErrors={formErrors}
      addressChange={addressChange}
      addAddress={addAddress} // removed the component name and give prob name
      isDefault={isDefault}
      defaultChange={defaultChange}
    />
  </SubPage>

我正在处理的应用程序将反应组件的名称作为小部件配置存储在浏览器存储中。其中一些组件已被删除,应用程序仍在尝试渲染它们。通过清除浏览器缓存,我能够解决我的问题。

所以我遇到了这个问题,我能够以一种奇怪的方式解决它。我想我会把它扔掉以防其他人遇到它并且变得绝望。

我有一个有条件渲染的 React 元素,它仅在 object 状态大于零时才渲染。在渲染函数中——当三元运算符被证明为真时,我收到了这个 post 的错误。我在渲染函数中使用了 <React.Fragment> - 这是我通常对 children 进行分组的方式,而不是使用较新的短语法 (<> and </>).

的较新方式

但是,当我将 <React.Fragment> 更改为短语法时 - 反应元素正确呈现并且错误不再出现。我查看了 Facebook 的 React-Fragment 文档,我看不出有任何理由相信两者之间存在巨大差异会导致这种情况。无论如何,下面是两个简化的代码片段供您查看。第一个演示产生错误的代码,第二个演示修复问题的代码。最下面是组件本身的render函数

希望有人觉得这有帮助。

代码示例 1 - 错误 条件渲染的 React 元素


  renderTimeFields = () => {
    return (
      <React.Fragment>
        <div className="align-left">
                <div className="input-row">
                  <label>Date: </label>
                  <input type="date" className="date" name="date" min={new Date().toISOString().split('T')[0]} required/>
                </div>
              </div>
              <div className="align-left sendOn-row">
                <div className="input-row">
                  <label>Time: </label>
                  <input type="time" className="time" name="time" required/>
                </div>
              </div>
      </React.Fragment>
    );
  }

代码示例 2 - 无错误 条件渲染的 React 元素


  renderTimeFields = () => {
    return (
      <>
        <div className="align-left">
                <div className="input-row">
                  <label>Date: </label>
                  <input type="date" className="date" name="date" min={new Date().toISOString().split('T')[0]} required/>
                </div>
              </div>
              <div className="align-left sendOn-row">
                <div className="input-row">
                  <label>Time: </label>
                  <input type="time" className="time" name="time" required/>
                </div>
              </div>
      </>
    );
  }

组件内的渲染函数

render() {
<form>
...
{emailsInActiveScript > 1 ? this.renderTimeFields() : null}
</form>
etc...
}

我的案例不像上面的许多答案所说的那样是一个重要问题。在我的中,我们使用包装器组件来执行一些翻译逻辑,而我错误地传递了子组件,如下所示:

const WrappedComponent = I18nWrapper(<ChildForm {...additionalProps} />);

当我应该将它作为函数传入时:

const WrappedComponent = I18nWrapper(() => <ChildForm {...additionalProps} />);

对我来说,我有两个同名但扩展名不同的文件(.js 和 .tsx)。因此,在我的导入中,我必须指定扩展名。

就我而言,VS Code 让我失望。

这是我的组件的层次结构:

<HomeScreen> =>  <ProductItemComponent> =>  <BadgeProductComponent>

我错误地导入了 ProductItemComponent。事实上,这个组件曾经在共享文件夹中,但后来被移到了主文件夹中。但是当我将文件移动到另一个文件夹时,导入没有更新并保持不变:

../shared/components

同时,组件运行良好,VS Code 没有高亮错误。但是当我向 ProductItemComponent 添加一个新的 BadgeProductComponent 时,我遇到了 Render Error 并认为问题出在新的 BadgeProductComponent 中,因为当这个组件被删除时,一切正常!

更重要的是,如果我通过热键转到具有 ../shared/components 地址的 ProductItemComponent,VS Code 会将我重定向到 Home 文件夹地址../home/components.

一般来说,检查所有组件级别的所有导入的正确性

我有类似的问题。发生这种情况是因为我在父组件中导入了一个已删除且实际上不存在的子组件。我正在审查父组件的每次导入,在这种情况下,父组件是 ListaNegra.js

对我来说,删除 Switch 解决了问题

import React from "react";
import "./styles.css";
import { Route, BrowserRouter, Routes } from "react-router-dom";
import LoginPage from "./pages/LoginPage";
import HomePage from "./pages/HomePage";

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route exact path="/" element={<HomePage />} />
        <Route path="/login" element={<LoginPage />} />
      </Routes>
    </BrowserRouter>
  );
}

我已经遇到过这个问题。我的解决方法是:

在文件配置路径:

const routes = [
    { path: '/', title: '', component: Home },
    { path: '*', title: '', component: NotFound }
]

至:

const routes = [
    { path: '/', title: '', component: <Home /> },
    { path: '*', title: '', component: <NotFound /> }
]

当我没有将任何内容undefined 作为值传递给我创建的子组件时,就会发生此问题。我这样做 <MyComponent src="" /> 导致了错误。然后改成了<MyComponent src=" " />因为我真的什么都不想传进去了。。。解决了。

对我来说,这是在我尝试将命名导入导入为默认导入时发生的,所以我得到了这个错误

import ProductCard from '../../../components/ProductCard' // that what caused the issue
Error: Element 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, or you might have mixed up default and named imports.

Check the render method of `TopVente`.

所以我不得不通过名称导入来修复它

import { ProductCard } from '../../../components/ProductCard'

就我而言,我将 Avatar 导入为 进口 { 头像 } 来自 'react-native-paper'; 在渲染时,我将 Avatar 元素包裹在 TouchableOpacity 中,这导致了上述问题。删除 TouchableOpacity 后,一切都很好。