React.createElement: il tipo non è valido - prevista una stringa


99

Si sta tentando di far funzionare correttamente react-router (v4.0.0) e react-hot-loader (3.0.0-beta.6), ma si ottiene il seguente errore nella console del browser:

Avvertenza: React.createElement: il tipo non è valido - ci si aspettava una stringa (per i componenti incorporati) o una classe / funzione (per i componenti compositi) ma ha ottenuto: undefined. Probabilmente hai dimenticato di esportare il tuo componente dal file in cui è definito.

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;

Se usi react-router-config assicurati di usare la componentproprietà invece di render, perché il pacchetto non supporta il successivo. Vedi di più su GitHub .
totymedli

Risposte:


130

Il più delle volte ciò è dovuto a un'esportazione / importazione errata.

Errore comune:

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

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

Possibile opzione:

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

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

Ci sono alcuni modi in cui potrebbe essere sbagliato, ma l'errore è dovuto a una mancata corrispondenza di importazione / esportazione il 60% delle volte, ogni volta.

modificare

In genere dovresti ottenere uno stacktrace che indichi una posizione approssimativa in cui si verifica l'errore. Questo generalmente segue subito dopo il messaggio che hai nella tua domanda originale.

Se non viene visualizzato, potrebbe valere la pena indagare sul motivo (potrebbe essere un'impostazione di build che ti manca). Indipendentemente da ciò, se non viene visualizzato, l'unica linea di condotta è restringere il campo in cui l'esportazione / importazione non riesce.

Purtroppo, l'unico modo per farlo, senza stacktrace è rimuovere manualmente ogni modulo / sottomodulo fino a quando non si ottiene più l'errore, quindi risalire lo stack.

Modifica 2

Tramite i commenti, era davvero un problema di importazione, in particolare l'importazione di un modulo che non esisteva


Ho esaminato la traccia che punta alla linea 12 di route.js. Quella linea è<IndexRoute component={Products} />
JoeTidee

2
Sei sicuro che l' indice route sia effettivamente parte di RR4? (Sono abbastanza sicuro che non lo sia)
Chris

Questo era il problema - grazie! Sono tornato alla v3.0.0
JoeTidee

Grandi cose buone. Sentiti libero di contrassegnarlo come risposta accettata in quanto aiuterà i futuri lettori a sapere come affrontare problemi simili
Chris

1
@PriyaRanjanSingh È impossibile capirlo da un piccolo commento. Puoi pubblicare una nuova domanda con i dettagli?
Chris,

16

Ricevo anche questo errore.

Stavo usando:

import BrowserRouter from 'react-router-dom';

Fix stava facendo questo, invece:

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


11

Prova questo

npm i react-router-dom@next

nella tua 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;


4

Ho avuto questo problema quando ho aggiunto un file css alla stessa cartella del file del componente.

La mia dichiarazione di importazione era:

import MyComponent from '../MyComponent'

il che andava bene quando c'era un solo file, MyComponent.jsx. (Ho visto questo formato in un esempio e l'ho provato, poi ho dimenticato di averlo fatto)

Quando ho aggiunto MyComponent.scss alla stessa cartella, l'importazione non è riuscita. Forse JavaScript ha caricato invece il file .scss e quindi non ci sono stati errori.

La mia conclusione: specifica sempre l'estensione del file anche se c'è un solo file, nel caso in cui ne aggiungi un altro in seguito.


3

Per i futuri googler:

La mia soluzione a questo problema è stata l'aggiornamento reacte react-domalle loro ultime versioni su NPM. Apparentemente stavo importando un componente che utilizzava la nuova sintassi dei frammenti ed era rotto nella mia vecchia versione di React.


2

Questo problema si è verificato quando ho avuto un cattivo riferimento nella mia dichiarazione di rendering / ritorno. (indica una classe inesistente). Controlla anche il codice dell'istruzione di ritorno per riferimenti errati.


2

Il più delle volte questo indica un errore di importazione / esportazione. Ma fai attenzione non solo a assicurarti che il file di riferimento nella traccia dello stack sia ben esportato, ma anche che questo file importi correttamente altri componenti . Nel mio caso l'errore è stato così:

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;


Grazie per questo commento! Ho questo problema da quando ho aggiornato alcuni pacchetti e ho fatto scorrere tutti questi commenti e nessuno di loro è in questione in questo codice. Ma era questo: il file problematico importa qualcos'altro che causa l'errore!
Diane Kaplan,

2

Penso che la cosa più importante da realizzare durante la risoluzione dei problemi di questo bug è che si manifesta quando si tenta di creare un'istanza di un componente che non esiste. Questo componente non deve essere importato. Nel mio caso stavo passando i componenti come proprietà. Ho dimenticato di aggiornare una delle chiamate per passare correttamente il componente dopo un po 'di refactoring. Sfortunatamente, poiché JS non è tipizzato staticamente, il mio bug non è stato rilevato e ci è voluto del tempo per capire cosa stava succedendo.

Per risolvere questo bug, ispeziona il componente prima di renderlo, per assicurarti che sia il tipo di componente che ti aspetti.


"si manifesta quando si tenta di istanziare un componente che non esiste" - questo è quello che è successo a me. Il componente è stato importato / esportato correttamente, ma mi stava passando come un oggetto di scena attraverso un percorso di autorizzazione nel reagiscono-router e dimenticato di cambiare il render={props => <Component {...props} />}verso component={Component}.
displacedtexan il

2

Mi mancava un frammento di reazione :


function Bar({ children }) {

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

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

Il codice precedente genera l'errore precedente. Ma questo lo risolve:

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

Mi è successo quando ho aggiunto ReactCollapsingTable ( yarn add react-collapsing-table). Sono riuscito ad alternare tra questo avviso (che ha provocato un errore di idratazione) e una "finestra non definita" che è stata rilevata all'interno del modulo della tabella di compressione-compressione compilato ... Anche il wrapping con <div>...</div>non aiuta più
superk

Alla fine ho riproposto l'intero progetto dall'inizio (invece di ricaricare a caldo) e il problema si è ripresentato. Ho trovato la soluzione qui: stackoverflow.com/a/43969990/2821963 (invece di import module from 'module-name', usa require(module-name).default)
superk

2

Matrice di componenti

Un modo comune per ottenere questo errore è utilizzare un array di componenti , con un indice di posizione utilizzato per selezionare il componente di cui eseguire il rendering dall'array. Ho visto un codice come questo molte volte:

const checkoutSteps = [Address, Shipment, Payment]

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

  const ToRender = checkoutSteps[step]

  return (
    <ToRender />
  )
}

Questo non è un codice errato necessario, ma se lo chiami con un indice sbagliato (ad esempio -1o 3in questo caso), il ToRendercomponente lancerà undefinedl' React.createElement: type is invalid...errore:

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

Una soluzione razionale

Dovresti proteggere te stesso ei tuoi colleghi da questo codice difficile da eseguire il debug utilizzando un approccio più esplicito, evitando numeri magici e utilizzando 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

E il tuo codice sarà simile a questo:

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

Vantaggi di questo approccio

  • il codice è più esplicito , puoi vedere chiaramente cosa vuoi rendere
  • non è necessario ricordare i numeri e il loro significato nascosto ( 1è per Indirizzo, 2 è per ...)
  • errori sono esplicite troppo
  • nessun mal di testa per i tuoi coetanei :)

1

Quello che mi mancava era che stavo usando

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

invece o la risposta corretta dovrebbe essere:

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

Ovviamente è necessario aggiungere il pacchetto npm react-router-dom :

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

1

Nel mio caso ho dimenticato di importare ed esportare i miei (nuovi) elementi chiamati dal render nel file index.js.


0

Nel mio caso, era importante l'ordine in cui crei il componente e il rendering. Stavo eseguendo il rendering del componente prima di crearlo. Il modo migliore è creare il componente figlio, quindi i componenti padre e quindi eseguire il rendering del componente padre. La modifica dell'ordine ha risolto il problema per me.


0

Nel mio caso ho dovuto solo passare da react-router-reduxa react-router-redux@next. Suppongo che debba essere stato un qualche problema di compatibilità.


0

In parole semplici, in qualche modo sta accadendo quanto segue:

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

Potrebbe non essere necessariamente correlato a un'importazione o esportazione errata:

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

    return (
        <MyComponent />
    );
}

0

Se si verifica questo errore durante il test di un componente, assicurarsi che ogni componente figlio venga visualizzato correttamente quando viene eseguito da solo, se uno dei componenti figlio dipende da risorse esterne per il rendering, provare a deriderlo con jest o qualsiasi altra lib beffarda:

Esempio:

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

0

Nel mio caso, l'errore si è verificato durante il tentativo di utilizzare ContextApi. Ho erroneamente usato:

const MyContext = () => createContext()

Ma avrebbe dovuto essere definito come:

const MyContext = createContext()

Lo sto pubblicando qui in modo che i futuri visitatori che si bloccano su un errore così stupido lo ottengano utile per evitare ore di mal di testa, perché questo non è causato da un'importazione / esportazione errata.


0

Anche la dipendenza circolare è una delle ragioni di ciò. [in generale]


0

Questo è un errore che è stato in qualche modo dovuto eseguire il debug. Come è stato detto molte volte, l'importazione / esportazione impropria può causare questo errore ma sorprendentemente ho ricevuto questo errore da un piccolo bug nel react-router-dom authentication setupmio caso di seguito:

IMPOSTAZIONE ERRATA:

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

CONFIGURAZIONE CORRETTA:

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

L'unica differenza era che stavo decostruendo tokenil file PrivateRoute component. A proposito, il token viene ottenuto in localstoragequesto const token = localStorage.getItem("authUser");modo, quindi se non è lì so che l'utente non è autenticato. Ciò può anche causare quell'errore.


0

È abbastanza semplice, davvero. Ho riscontrato questo problema quando ho iniziato a codificare React e il problema è quasi sempre dovuto all'importazione:

import React, { memo } from 'react';

Puoi usare la destrutturazione di questo perché react lib ha una proprietà come memo, ma non puoi destrutturare qualcosa di simile

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

perché non è un oggetto.

Spero che sia d'aiuto!


0

Reagisci frammento

risolto il problema per me

Codice di errore:

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

Fix

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

0

Non è necessario un problema diretto relativo all'importazione / esportazione. Nel mio caso, stavo eseguendo il rendering di un elemento figlio all'interno di un elemento genitore e l'elemento figlio ha un elemento / tag jsx che viene utilizzato ma non importato. L'ho importato e l'ho usato poi ha risolto il problema. Quindi il problema era negli elementi jsx che si trovano all'interno dell'elemento figlio NON nell'esportazione dell'elemento figlio stesso.


-1

Ho appena trascorso 30 minuti cercando di risolvere questo problema di base BASE.

Il mio problema era che stavo importando elementi nativi di reazione

per esempio import React, { Text, Image, Component } from 'react';

E cercando di usarli, il che mi ha fatto ricevere questo errore.

Una volta passato da <Text>a <p>e <Image>a <img>tutto ha funzionato come previsto.


-1

Ho ricevuto questo errore e nessuna delle risposte era il mio caso, potrebbe aiutare qualcuno che cerca su Google:

Stavo definendo un Proptype sbagliato:

ids: PropTypes.array(PropTypes.string)

Dovrebbe essere:

ids: PropTypes.arrayOf(PropTypes.string)

VSCode e l'errore di compilazione non mi hanno dato un suggerimento corretto.


-2

MODIFICARE

Stai complessando il processo. Basta fare questo:

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;

Sei sicuro che il problema provenga da qui? E non dalle pagine stesse?
John Smith
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.