205

试图让 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() );

路线.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;
4

39 回答 39

228

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

常见错误:

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

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

于 2017-03-15T15:29:37.177 回答
43

我也收到了这个错误。

我正在使用:

import BrowserRouter from 'react-router-dom';

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

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

于 2018-01-04T17:56:53.317 回答
14

试试这个

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;
于 2017-05-09T11:25:16.197 回答
12

组件数组

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

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代表...)
  • 错误也很明确
  • 让你的同龄人不头疼:)
于 2020-06-08T09:05:22.413 回答
9

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

就我而言,我通过更改来修复它

import Provider from 'react-redux'

import { Provider } from 'react-redux'
于 2018-03-13T15:21:42.757 回答
4

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

我的导入声明是:

import MyComponent from '../MyComponent'

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

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

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

于 2018-02-27T18:17:53.107 回答
4

我也收到了这个错误。

我正在使用:

import ReactDOM from 'react-dom';

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

import {ReactDOM} from 'react-dom';

于 2021-02-16T04:51:16.180 回答
3

对于未来的谷歌人:

我对这个问题的解决方案是升级reactreact-domNPM 上的最新版本。显然我正在导入一个使用新片段语法的组件,它在我的旧版本 React 中被破坏了。

于 2018-03-04T09:28:18.317 回答
3

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

于 2019-05-05T12:29:44.003 回答
3

大多数情况下,这表明存在导入/导出错误。但请注意,不仅要确保堆栈跟踪中的引用文件本身被很好地导出,而且还要确保该文件正确地导入了其他组件。在我的情况下,错误是这样的:

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;

于 2019-06-28T23:05:57.670 回答
3

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

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

于 2019-09-21T14:54:13.153 回答
3

这意味着您的导入/导出不正确

  • 检查新添加import/exports的 .
  • 就我而言,我使用了不必要的大括号。当我删除这些大括号时,问题自动解决了。
import { OverlayTrigger } from 'react-bootstrap/OverlayTrigger';
于 2020-11-12T10:47:15.343 回答
3

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

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

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

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

../shared/components

同时,该组件运行良好,VS Code 没有突出显示错误。但是当我在 ProductItemComponent 中添加一个新的 BadgeProductComponent 时,我出现了一个渲染错误,并认为问题出在新的 BadgeProductComponent 中,因为当这个组件被移除时,一切正常!

更重要的是,如果我通过热键访问具有 ../共享/components 地址的 ProductItemComponent,那么 VS Code 会将我重定向到地址为 ../home /components 的主文件

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

于 2021-09-03T12:38:48.957 回答
2

我错过了一个反应片段


function Bar({ children }) {

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

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

上面的代码抛出了上面的错误。但这解决了它:

<Bar>
  <>
    <Baz/>
    <Qux/>
  </>
</Bar>
于 2019-11-12T12:59:20.493 回答
2

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

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

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

const WrappedComponent = I18nWrapper(() => <ChildForm {...additionalProps} />);
于 2021-08-16T13:59:34.860 回答
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
于 2017-08-01T11:21:35.123 回答
1

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

示例:

jest.mock('pathToChildComponent', () => 'mock-child-component')
于 2019-06-11T14:13:23.723 回答
1

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

const MyContext = () => createContext()

但它应该被定义为:

const MyContext = createContext()

我将其发布在这里,以便将来陷入这种愚蠢错误的访问者将有助于避免数小时的头痛,因为这不是由不正确的导入/导出引起的。

于 2019-07-12T08:03:37.523 回答
1

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

于 2019-10-25T13:09:29.503 回答
1

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

于 2020-01-20T11:44:36.767 回答
1

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

import React, { memo } from 'react';

你可以使用解构这个,因为 react lib 有一个属性作为备忘录,但是你不能解构这样的东西

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

因为它不是一个对象。

希望能帮助到你!

于 2020-03-10T07:57:04.167 回答
1
xxxxx.prototype = {
  dxxxx: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};

您必须添加// eslint-disable-line react/forbid-prop-types,然后它才能工作!

于 2020-11-02T04:24:53.173 回答
1

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

于 2021-02-26T19:29:00.957 回答
1

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

于 2021-08-27T16:20:35.587 回答
0

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

于 2018-06-15T14:59:14.500 回答
0

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

于 2018-06-29T03:46:08.333 回答
0

简而言之,以某种方式发生了以下情况:

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

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

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

    return (
        <MyComponent />
    );
}
于 2018-12-18T16:53:46.920 回答
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" }} />)}
    />
);

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

于 2020-03-07T10:51:59.657 回答
0

反应片段

为我解决了这个问题

错误代码:

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

使固定

 return (
      <React.Fragment>
        <section className={classes.itemForm}>
         <Card>
         </Card> 
        </section>
      </React.Fragment>
  );
于 2020-05-08T06:29:55.100 回答
0

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

于 2020-05-25T04:57:09.567 回答
0

我得到了完全相同的错误,请改为:

npm install react-router@next 
react-router-dom@next
npm install --save history
于 2020-11-12T06:51:32.907 回答
0

就我而言,我添加了与道具相同的自定义组件而不是实际道具

   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>
于 2021-02-21T14:36:53.560 回答
0

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

我有一个有条件地渲染反应元素,它仅在状态对象大于零时渲染。在渲染函数中 - 当三元运算符被证明为真时,我收到了这篇文章所涉及的错误。我在我的渲染函数中使用了 a <React.Fragment>- 这是我通常将孩子分组的方式,而不是使用较新的短语法 ( <> and </>) 的较新方式。

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

希望有人觉得这很有帮助。

代码示例 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...
}
于 2021-07-10T02:43:31.417 回答
0

对我来说,删除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>
  );
}
于 2022-01-18T10:53:01.760 回答
-1

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

我的问题是我正在导入反应原生元素

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

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

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

于 2019-03-31T22:13:23.477 回答
-1

我收到了这个错误,没有一个回复是我的情况,它可能有助于有人用谷歌搜索:

我定义了一个错误的 Proptype:

ids: PropTypes.array(PropTypes.string)

它应该是:

ids: PropTypes.arrayOf(PropTypes.string)

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

于 2019-05-08T16:06:02.087 回答
-1
// @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>
于 2021-02-03T20:05:14.847 回答
-1

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

在此处输入图像描述

于 2021-09-25T05:05:36.407 回答
-3

编辑

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

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

路线.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;
于 2017-03-15T15:14:43.703 回答