React.createElement: тип недійсний - очікується рядок


108

Намагаючись отримати реакційний маршрутизатор (v4.0.0) та реактор-гарячий завантажувач (3.0.0-beta.6), щоб грати приємно, але отримуємо таку помилку в консолі браузера:

Попередження: тип React.createElement: недійсний - очікується рядок (для вбудованих компонентів) або клас / функція (для складених компонентів), але отримано: 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() );

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;

Якщо ви використовуєте response-router-config, переконайтеся, що ви використовуєте componentвластивість замість render, оскільки пакет не підтримує пізніші. Дивіться більше на GitHub .
totymedli

Відповіді:


145

Здебільшого це пов’язано з неправильним експортом / імпортом.

Поширена помилка:

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

Через коментарі це справді була проблема імпорту, зокрема імпортування неіснуючого модуля


Переглянули трасування, яке вказує на рядок 12 із route.js. Цей рядок<IndexRoute component={Products} />
JoeTidee

2
Ви впевнені, що маршрут індексу насправді є частиною RR4? (Я майже впевнений, що це не так)
Кріс

Це було питання - дякую! Я повернувся до v3.0.0
JoeTidee

Чудова, хороша штука. Не соромтеся позначати це як прийняту відповідь, оскільки це допоможе майбутнім читачам знати, як підходити до подібних питань
Кріс

1
@PriyaRanjanSingh Неможливо відрізнити за допомогою лише невеликого коментаря. Чи можете ви опублікувати нове запитання з деталями?
Кріс,

18

Я також отримував цю помилку.

Я використовував:

import BrowserRouter from 'react-router-dom';

Натомість Fix робив це:

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


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 exportі default export. Див. Коли слід використовувати фігурні дужки для імпорту ES6?

У моєму випадку я виправив це, змінивши з

import Provider from 'react-redux'

до

import { Provider } from 'react-redux'

я звузив свою проблему до цього постачальника. однак я вже використовую нотацію {Provider}.
Джейсон Г

4

У мене виникла ця проблема, коли я додав файл css до тієї ж папки, що і файл компонента.

Моєю заявою про імпорт було:

import MyComponent from '../MyComponent'

що було добре, коли існував лише один файл, MyComponent.jsx. (Я побачив цей формат у прикладі і спробував, а потім забув, що це зробив)

Коли я додав MyComponent.scss до тієї ж папки, імпорт тоді не вдався. Можливо, натомість JavaScript завантажив файл .scss, і тому помилки не було.

Мій висновок: завжди вказуйте розширення файлу, навіть якщо файл лише один, на випадок, якщо ви додасте інший пізніше.


3

Для майбутніх гуглерів:

Моїм рішенням цієї проблеми було оновлення reactта react-domновітні версії NPM. Очевидно, я імпортував Компонент, який використовував новий синтаксис фрагментів, і він був порушений у моїй попередній версії React.


3

Масив компонентів

Поширеним способом отримати цю помилку є використання масиву компонентів , з позиційним індексом, що використовується для вибору компонента, який відображатиметься з масиву. Я бачив подібний код багато разів:

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 для ...)
  • помилки теж явні
  • немає головного болю для однолітків :)

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 не набирається статично, мою помилку не зловили, і знадобився певний час, щоб зрозуміти, що відбувається.

Щоб усунути цю помилку, перевірте компонент перед тим, як його відтворити, щоб переконатися, що це тип компонента, який ви очікуєте.


"це виявляється, коли ви намагаєтеся створити екземпляр компонента, який не існує" - ось що сталося зі мною. Компонент було імпортовано / експортовано правильно, але я передавав його як пропір через авторизаційний маршрут у response-router і забув змінити render={props => <Component {...props} />}на component={Component}.
переміщений

2

Мені не вистачало фрагмента React :


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

1

Мені не вистачало того, що я використовував

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

замість цього або правильна відповідь повинна бути:

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

Звичайно, вам потрібно додати пакет npm response -router-dom :

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

1

У моєму випадку я забув імпортувати та експортувати свої (нові) елементи, викликані методом render у файлі index.js.


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.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" }} />)}
    />
);

Єдина різниця полягала в тому, що я проводив деконструкцію tokenв PrivateRoute component. До речі, маркер отриманий localstorageтаким const token = localStorage.getItem("authUser");чином, тому, якщо його немає, я знаю, що користувач не аутентифікований. Це також може спричинити цю помилку.


0

Насправді це досить просто. Я отримав цю проблему, коли почав кодувати React, і проблема майже завжди полягає в тому, що імпорт:

import React, { memo } from 'react';

Ви можете використовувати деструктуризацію цього, оскільки реакція lib має властивість нагадувати, але ви не можете деструктурувати щось подібне

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

бо це не об’єкт.

Сподіваюся, це допоможе!


0

React.Fragment

вирішив проблему для мене

Код помилки:

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

Виправити

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

0

Це не обов'язково пряме питання, пов'язане з імпортом / експортом. У моєму випадку я відображав дочірній елемент всередині батьківського елемента, і дочірній елемент має елемент / тег jsx, який використовується, але не імпортується. Я імпортував його і використав, тоді це вирішило проблему. Отже, проблема полягала в елементах jsx, які знаходяться всередині дочірнього елемента, а НЕ експорт самого дочірнього елемента.


0

xxxxx.prototype = {dxxxx: PropTypes.object.isRequired, // eslint-disable-line-response / prohib-prop-types};

Ви повинні додати // eslint-disable-line react/forbid-prop-types, тоді це буде спрацьовано!


-1

Я просто витратив 30 хвилин, намагаючись вирішити це базове основне питання.

Моя проблема полягала в тому, що я імпортував рідні елементи реакції

напр import React, { Text, Image, Component } from 'react';

І спроба їх використовувати, що призвело до того, що я отримав цю помилку.

Після того, як я перейти від <Text>до <p>і <Image>на <img>все працювало , як очікувалося.


-1

Я отримував цю помилку, і жодна з відповідей не була моєю справою, це може допомогти комусь погуглити:

Я неправильно визначав проптип:

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

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;

Ви впевнені, що проблема походить звідси? А не з самих сторінок?
Джон Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.