React.createElement: le type n'est pas valide - une chaîne attendue

99

Essayer d'obtenir react-router (v4.0.0) et react-hot-loader (3.0.0-beta.6) pour jouer correctement, mais obtenir l'erreur suivante dans la console du navigateur:

Avertissement: React.createElement: type n'est pas valide - attend une chaîne (pour les composants intégrés) ou une classe / fonction (pour les composants composites) mais a: undefined. Vous avez probablement oublié d'exporter votre composant à partir du fichier dans lequel il est défini.

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;
JoeTidee
la source
Si vous utilisez react-router-config, assurez-vous d'utiliser la componentpropriété à la place de render, car le package ne prend pas en charge la version ultérieure. En savoir plus sur GitHub .
totymedli

Réponses:

131

La plupart du temps, cela est dû à une exportation / importation incorrecte.

Erreur courante:

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

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

Option possible:

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

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

Il y a plusieurs façons dont cela pourrait être erroné, mais cette erreur est due à une incompatibilité d'importation / exportation 60% du temps, à chaque fois.

Éditer

Typiquement vous devriez obtenir un stacktrace qui indique un emplacement approximatif de l'endroit où l'échec se produit. Cela suit généralement juste après le message que vous avez dans votre question initiale.

S'il ne s'affiche pas, il peut être utile de rechercher pourquoi (il peut s'agir d'un paramètre de construction qui vous manque). Quoi qu'il en soit, si cela n'apparaît pas, le seul plan d'action est de réduire l'exportation / importation échoue.

Malheureusement, la seule façon de le faire, sans trace de pile, est de supprimer manuellement chaque module / sous-module jusqu'à ce que vous n'obteniez plus l'erreur, puis remontez la pile.

Modifier 2

Via les commentaires, c'était en effet un problème d'importation, en particulier l'importation d'un module qui n'existait pas

Chris
la source
J'ai regardé la trace qui pointe vers la ligne 12 de routes.js. Cette ligne est<IndexRoute component={Products} />
JoeTidee
2
Etes-vous sûr que la route d'index fait partie de RR4? (Je suis sûr que ce n'est pas le cas)
Chris
C'était le problème - merci! Je suis revenu à la v3.0.0
JoeTidee
Super, bon truc. N'hésitez pas à la marquer comme la réponse acceptée car elle aidera les futurs lecteurs à savoir comment aborder des problèmes similaires
Chris
1
@PriyaRanjanSingh Il est impossible de dire à partir d'un simple petit commentaire. Pouvez-vous publier une nouvelle question avec des détails?
Chris
16

J'avais aussi cette erreur.

J'utilisais:

import BrowserRouter from 'react-router-dom';

Fix faisait cela, à la place:

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

Pedro Gonçalves
la source
11

Essaye ça

npm i react-router-dom@next

dans votre 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;
Ignace Andrew
la source
5

Vous devez être conscient de named exportet default export. Voir Quand dois-je utiliser des accolades pour l'importation ES6?

Dans mon cas, je l'ai corrigé en passant de

import Provider from 'react-redux'

à

import { Provider } from 'react-redux'
onmyway133
la source
J'ai réduit mon problème à ce fournisseur. cependant, j'utilise déjà la notation {Provider}.
Jason G
4

J'ai eu ce problème lorsque j'ai ajouté un fichier css dans le même dossier que le fichier du composant.

Ma déclaration d'importation était:

import MyComponent from '../MyComponent'

ce qui était bien quand il n'y avait qu'un seul fichier, MyComponent.jsx. (J'ai vu ce format dans un exemple et l'ai essayé, puis j'ai oublié que je l'avais fait)

Lorsque j'ai ajouté MyComponent.scss dans le même dossier, l'importation a échoué. Peut-être que JavaScript a chargé le fichier .scss à la place et qu'il n'y a donc pas eu d'erreur.

Ma conclusion: spécifiez toujours l'extension du fichier même s'il n'y a qu'un seul fichier, au cas où vous en ajouteriez un autre plus tard.

Petit cerveau
la source
3

Pour les futurs googleurs:

Ma solution à ce problème était de mettre à niveau reactet react-domvers leurs dernières versions sur NPM. Apparemment, j'importais un composant qui utilisait la nouvelle syntaxe de fragment et il était cassé dans mon ancienne version de React.

colinbr96
la source
2

Ce problème m'est apparu lorsque j'avais une mauvaise référence dans mon instruction de rendu / retour. (pointez sur une classe non existante). Vérifiez également votre code de déclaration de retour pour les mauvaises références.

Cornélius
la source
2

La plupart du temps, cela indique une erreur d'import / export. Mais faites attention non seulement à vous assurer que le fichier référencé dans la trace de pile est bien exporté lui-même, mais également à ce que ce fichier importe correctement les autres composants . Dans mon cas, l'erreur était comme ceci:

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;

Felipe Suárez
la source
Merci pour ce commentaire! J'ai ce problème depuis la mise à jour de certains packages, et j'ai parcouru tous ces commentaires et aucun d'entre eux n'est en question dans ce code. Mais c'était tout - le fichier de problème importe autre chose qui est à l'origine de l'erreur!
Diane Kaplan
2

Je pense que la chose la plus importante à réaliser lors du dépannage de ce bogue est qu'il se manifeste lorsque vous essayez d'instancier un composant qui n'existe pas. Ce composant n'a pas besoin d'être importé. Dans mon cas, je passais des composants en tant que propriétés. J'ai oublié de mettre à jour l'un des appels pour passer correctement le composant après une refactorisation. Malheureusement, comme JS n'est pas typé statiquement, mon bogue n'a pas été détecté et il a fallu du temps pour comprendre ce qui se passait.

Pour résoudre ce bogue, inspectez le composant avant de le rendre, pour vous assurer qu'il s'agit du type de composant que vous attendez.

Alex
la source
"cela se manifeste lorsque vous essayez d'instancier un composant qui n'existe pas" - c'est ce qui m'est arrivé. Le composant a été importé / exporté correctement mais je le transmettais comme accessoire via une route d'autorisation dans react-router et j'ai oublié de changer le render={props => <Component {...props} />}en component={Component}.
déplacé
2

Il me manquait un fragment de réaction :


function Bar({ children }) {

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

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

Le code ci-dessus renvoie l'erreur ci-dessus. Mais cela corrige le problème:

<Bar>
  <>
    <Baz/>
    <Qux/>
  </>
</Bar>
Paul Razvan Berg
la source
Cela m'est arrivé lorsque j'ai ajouté ReactCollapsingTable ( yarn add react-collapsing-table). J'ai réussi à alterner entre cet avertissement (qui a entraîné une erreur d'hydratation) et une `` fenêtre n'est pas définie '' qui a été détectée à l'intérieur du module compilé react-collapsing-table ... Même enrouler avec <div>...</div>n'aide plus
superk
Finalement, j'ai re-transpilé tout le projet depuis le début (au lieu de recharger à chaud) et le problème est réapparu. import module from 'module-name'require(module-name).default
J'ai
2

Tableau de composants

Un moyen courant d'obtenir cette erreur consiste à utiliser un tableau de composants , avec un index de position utilisé pour sélectionner le composant à restituer à partir du tableau. J'ai vu un code comme celui-ci plusieurs fois:

const checkoutSteps = [Address, Shipment, Payment]

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

  const ToRender = checkoutSteps[step]

  return (
    <ToRender />
  )
}

Ce n'est pas un mauvais code nécessaire, mais si vous l'appelez avec un mauvais index (par exemple -1, ou 3dans ce cas), le ToRendercomposant lancera undefinedl' React.createElement: type is invalid...erreur:

<Checkout step={0} /> // <Address />
<Checkout step={1} /> // <Shipment />
<Checkout step={2} /> // <Payment />
<Checkout step={3} /> // undefined
<Checkout step={-1} /> // undefined

Une solution rationnelle

Vous devez vous protéger et protéger vos collègues de ce code difficile à déboguer en utilisant une approche plus explicite, en évitant les nombres magiques et en utilisant les 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

Et votre code ressemblera à ceci:

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

Avantages de cette approche

  • le code est plus explicite , vous pouvez clairement voir ce que vous voulez rendre
  • vous n'avez pas besoin de vous souvenir des chiffres et de leur caché signification ( 1est pour l'adresse, 2 est pour ...)
  • les erreurs sont explicites aussi
  • pas de mal de tête pour vos pairs :)
lifeisfoo
la source
1

Ce qui me manquait, c'était que j'utilisais

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

à la place ou la bonne réponse devrait être:

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

Bien sûr, vous devez ajouter le package npm react -router-dom :

npm install react-router-dom@next --save
Pranav Singh
la source
1

Dans mon cas, j'ai oublié d'importer et d'exporter mes (nouveaux) éléments appelés par le rendu dans le fichier index.js.

Borjovsky
la source
0

Dans mon cas, l'ordre dans lequel vous créez le composant et le rendu importait. J'étais en train de rendre le composant avant de le créer. Le meilleur moyen est de créer le composant enfant, puis les composants parents, puis de rendre le composant parent. La modification de la commande a résolu le problème pour moi.

Mahesh Kumar Ronde
la source
0

Dans mon cas, je devais juste passer de react-router-reduxà react-router-redux@next. Je suppose que cela a dû être une sorte de problème de compatibilité.

dspacejs
la source
0

En termes simples, en quelque sorte, ce qui suit se produit:

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

Cela peut ne pas nécessairement être lié à une importation ou une exportation incorrecte:

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

    return (
        <MyComponent />
    );
}
falsarella
la source
0

Si vous rencontrez cette erreur lors du test d'un composant, assurez-vous que chaque composant enfant est correctement rendu lorsqu'il est exécuté seul, si l'un de vos composants enfant dépend de ressources externes pour le rendu, essayez de le simuler avec jest ou toute autre bibliothèque moqueuse:

Exemple:

jest.mock('pathToChildComponent', () => 'mock-child-component')
ZEE
la source
0

Dans mon cas, l'erreur s'est produite lors de la tentative d'utilisation de ContextApi. J'ai utilisé par erreur:

const MyContext = () => createContext()

Mais cela aurait dû être défini comme:

const MyContext = createContext()

Je le publie ici afin que les futurs visiteurs qui se retrouvent coincés sur une erreur aussi stupide puissent éviter des heures de maux de tête, car cela n'est pas causé par une importation / exportation incorrecte.

Bhojendra Rauniyar
la source
0

La dépendance circulaire en est également une des raisons. [en général]

Maor Dahan
la source
0

C'est une erreur qui a dû être déboguée. Comme cela a été dit à plusieurs reprises, une importation / exportation incorrecte peut provoquer cette erreur, mais étonnamment, j'ai eu cette erreur à cause d'un petit bogue dans monreact-router-dom authentication setup ci-dessous, c'est mon cas:

MAUVAISE CONFIGURATION:

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

CONFIGURATION CORRECT:

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

La seule différence était que je déconstruisais le tokendans le PrivateRoute component. Au fait, le jeton est obtenu de localstoragecette const token = localStorage.getItem("authUser");manière, donc s'il n'est pas là, je sais que l'utilisateur n'est pas authentifié. Cela peut également provoquer cette erreur.

Lawrence Eagles
la source
0

C'est assez simple, vraiment. J'ai eu ce problème lorsque j'ai commencé à coder React, et le problème est presque toujours dû au fait que l'importation:

import React, { memo } from 'react';

Vous pouvez utiliser la déstructuration car react lib a une propriété comme mémo, mais vous ne pouvez pas déstructurer quelque chose comme ça

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

car ce n'est pas un objet.

J'espère que ça aide!

Thuan Tran
la source
0

Réagir Fragment

a corrigé le problème pour moi

Code d'erreur:

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

Réparer

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

Ce n'est pas nécessairement un problème direct lié à l'importation / exportation. Dans mon cas, je rendais un élément enfant à l'intérieur d'un élément parent et l'élément enfant a un élément / tag jsx qui est utilisé mais pas importé. Je l'ai importé et je l'ai utilisé, puis il a résolu le problème. Donc, le problème était dans les éléments jsx qui sont à l'intérieur de l'élément enfant PAS l'exportation de l'élément enfant lui-même.

Tanaka
la source
-1

Je viens de passer 30 minutes à essayer de résoudre ce problème de base BASIC.

Mon problème était que j'importais des éléments natifs de réaction

par exemple import React, { Text, Image, Component } from 'react';

Et essayer de les utiliser, ce qui m'a fait recevoir cette erreur.

Une fois que je passe de <Text>la <p>et <Image>à <img>tout ce qui a fonctionné comme prévu.

Jacksonkr
la source
-1

J'obtenais cette erreur et aucune des réponses n'était mon cas, cela pourrait aider quelqu'un à rechercher sur Google:

Je définissais mal un Proptype:

ids: PropTypes.array(PropTypes.string)

Ça devrait être:

ids: PropTypes.arrayOf(PropTypes.string)

VSCode et l'erreur de compilation ne m'ont pas donné un indice correct.

llessa
la source
-2

ÉDITER

Vous complexifiez le processus. Faites juste ceci:

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;
John Smith
la source
Êtes-vous sûr que le problème vient d'ici? Et pas des pages elles-mêmes?
John Smith