React.createElement: tipo é inválido - esperava uma string

99

Tentando fazer com que react-router (v4.0.0) e react-hot-loader (3.0.0-beta.6) funcionem bem, mas obtendo o seguinte erro no console do navegador:

Aviso: React.createElement: type é inválido - esperava uma string (para componentes embutidos) ou uma classe / função (para componentes compostos), mas obteve: indefinido. Você provavelmente se esqueceu de exportar seu componente do arquivo em que está definido.

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
fonte
Se você usar react-router-config, certifique-se de usar a componentpropriedade em vez de render, porque o pacote não suporta o último. Veja mais no GitHub .
totymedli de

Respostas:

130

Na maioria das vezes, isso se deve a uma exportação / importação incorreta.

Erro comum:

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

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

Opção possível:

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

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

Existem algumas maneiras de estar errado, mas esse erro é devido a uma incompatibilidade de importação / exportação 60% das vezes, sempre.

Editar

Normalmente, você deve obter um rastreamento de pilha que indica uma localização aproximada de onde a falha ocorre. Isso geralmente vem logo após a mensagem que você tem em sua pergunta original.

Se não aparecer, pode valer a pena investigar o porquê (pode ser uma configuração de construção que você está perdendo). Independentemente disso, se não aparecer, o único curso de ação é restringir onde a exportação / importação está falhando.

Infelizmente, a única maneira de fazer isso, sem um rastreamento de pilha, é remover manualmente cada módulo / submódulo até não receber mais o erro e, em seguida, voltar a subir na pilha.

Editar 2

Por meio de comentários, era realmente um problema de importação, especificamente importar um módulo que não existia

Chris
fonte
Observei o traço que aponta para a linha 12 de routes.js. Essa linha é<IndexRoute component={Products} />
JoeTidee
2
Tem certeza de que a rota do índice realmente faz parte do RR4? (Tenho quase certeza que não)
Chris,
Esse era o problema - obrigado! Eu voltei para v3.0.0
JoeTidee
Ótimo, bom material. Sinta-se à vontade para marcá-la como a resposta aceita, pois ajudará futuros leitores a saber como abordar questões semelhantes
Chris,
1
@PriyaRanjanSingh É impossível dizer apenas com um pequeno comentário. Você pode postar uma nova pergunta com detalhes?
Chris
16

Eu estava recebendo esse erro também.

Eu estava usando:

import BrowserRouter from 'react-router-dom';

Em vez disso, Fix estava fazendo isso:

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

Pedro Gonçalves
fonte
11

Tente isto

npm i react-router-dom@next

em seu 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;
Inácio André
fonte
5

Você precisa estar ciente de named exporte default export. Consulte Quando devo usar chaves para importação ES6?

No meu caso, corrigi mudando de

import Provider from 'react-redux'

para

import { Provider } from 'react-redux'
onmyway133
fonte
Limitei meu problema a este provedor. no entanto, já estou usando a notação {Provider}.
Jason G
4

Tive esse problema quando adicionei um arquivo css à mesma pasta do arquivo do componente.

Minha declaração de importação foi:

import MyComponent from '../MyComponent'

o que era bom quando havia apenas um único arquivo, MyComponent.jsx. (Eu vi esse formato em um exemplo e tentei, mas esqueci que tinha feito isso)

Quando adicionei MyComponent.scss à mesma pasta, a importação falhou. Talvez o JavaScript tenha carregado o arquivo .scss e, portanto, não houve erro.

Minha conclusão: especifique sempre a extensão do arquivo, mesmo que haja apenas um arquivo, caso você adicione outro posteriormente.

Pequeno cérebro
fonte
3

Para futuros googlers:

Minha solução para esse problema foi atualizar reacte react-dompara suas versões mais recentes no NPM. Aparentemente, eu estava importando um componente que estava usando a nova sintaxe de fragmento e foi quebrado na minha versão anterior do React.

colinbr96
fonte
2

Este problema me ocorreu quando eu tinha uma referência incorreta em minha instrução render / return. (aponte para uma classe não existente). Verifique também se há referências incorretas no código da instrução de retorno.

Cornelius
fonte
2

Na maioria das vezes, isso indica um erro de importação / exportação. Mas tome cuidado não apenas para certificar-se de que o arquivo referenciado no rastreamento de pilha seja bem exportado, mas também de que este arquivo esteja importando outros componentes corretamente. No meu caso, o erro foi assim:

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
fonte
Obrigado por este comentário! Eu tenho esse problema desde a atualização de alguns pacotes, e tenho percorrido todos esses comentários e nenhum deles está em questão neste código. Mas era isso - o arquivo com problema importa outra coisa que está causando o erro!
Diane Kaplan
2

Acho que a coisa mais importante a se perceber ao solucionar esse bug é que ele se manifesta quando você tenta instanciar um componente que não existe. Este componente não precisa ser importado. No meu caso, estava passando componentes como propriedades. Esqueci de atualizar uma das chamadas para passar corretamente o componente após alguma refatoração. Infelizmente, uma vez que JS não é digitado estaticamente, meu bug não foi detectado e levou algum tempo para descobrir o que estava acontecendo.

Para solucionar esse bug, inspecione o componente antes de renderizá-lo, para ter certeza de que é o tipo de componente que você espera.

Alex
fonte
"ele se manifesta quando você tenta instanciar um componente que não existe" - foi o que aconteceu comigo. O componente foi importado / exportado corretamente, mas eu estava passando-o como um prop por uma rota de autorização no react-router e esqueci de mudar o render={props => <Component {...props} />}para component={Component}.
deslocadotexan
2

Estava faltando um Fragmento de Reação :


function Bar({ children }) {

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

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

O código acima gera o erro acima. Mas isso corrige:

<Bar>
  <>
    <Baz/>
    <Qux/>
  </>
</Bar>
Paul Razvan Berg
fonte
Aconteceu comigo quando adicionei ReactCollapsingTable ( yarn add react-collapsing-table). Consegui alternar entre este aviso (que resultou em um erro de hidratação) e uma 'janela não definida' que foi detectada dentro do módulo da tabela <div>...</div>
reativa
Eventualmente, transpilei todo o projeto desde o início (em vez de recarregar a quente) e o problema voltou a ocorrer. Encontrou a solução aqui: stackoverflow.com/a/43969990/2821963 (em vez de import module from 'module-name', use require(module-name).default)
superk
2

Matriz de componentes

Uma maneira comum de obter esse erro é usar uma matriz de componentes , com um índice posicional usado para selecionar o componente a ser renderizado da matriz. Eu vi um código como este muitas vezes:

const checkoutSteps = [Address, Shipment, Payment]

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

  const ToRender = checkoutSteps[step]

  return (
    <ToRender />
  )
}

Isso não é necessariamente um código ruim, mas se você chamá-lo com um índice incorreto (por exemplo -1, ou 3neste caso), o ToRendercomponente estará undefined, gerando o React.createElement: type is invalid...erro:

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

Uma solução racional

Você deve proteger você e seus colegas deste código difícil de depurar usando uma abordagem mais explícita, evitando números mágicos e usando 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 seu código será semelhante a este:

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

Benefícios desta abordagem

  • o código é mais explícito , você pode ver claramente o que deseja renderizar
  • você não precisa se lembrar dos números e seus significados ocultos ( 1é para Endereço, 2 é para ...)
  • erros são explícitos também
  • sem dor de cabeça para seus colegas :)
lifeisfoo
fonte
1

O que faltou para mim era que eu estava usando

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

em vez disso, a resposta correta deve ser:

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

Claro, você precisa adicionar o pacote npm react -router-dom :

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

No meu caso, esqueci de importar e exportar meus (novos) elementos chamados pelo render no arquivo index.js.

Borjovsky
fonte
0

No meu caso, a ordem em que você cria o componente e renderiza é importante. Eu estava renderizando o componente antes de criá-lo. A melhor maneira é criar o componente filho e, a seguir, os componentes pai e, a seguir, renderizar o componente pai. Alterar o pedido resolveu o problema para mim.

Mahesh Kumar Ronde
fonte
0

No meu caso, apenas precisei atualizar de react-router-reduxpara react-router-redux@next. Estou assumindo que deve ter sido algum tipo de problema de compatibilidade.

dspacejs
fonte
0

Em palavras simples, de alguma forma o seguinte está acontecendo:

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

Pode não estar necessariamente relacionado a alguma importação ou exportação incorreta:

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

    return (
        <MyComponent />
    );
}
falsarella
fonte
0

Se você tiver esse erro ao testar um componente, certifique-se de que cada componente filho seja renderizado corretamente quando executado sozinho. Se um de seus componentes filho depender de recursos externos para renderizar, tente simular com jest ou qualquer outro lib de simulação:

Exemplo:

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

No meu caso, o erro ocorreu ao tentar usar ContextApi. Eu usei por engano:

const MyContext = () => createContext()

Mas deveria ter sido definido como:

const MyContext = createContext()

Estou postando aqui para que futuros visitantes que ficarem presos em um erro tão idiota possam ajudá-lo a evitar horas de dor de cabeça, porque isso não é causado por importação / exportação incorreta.

Bhojendra Rauniyar
fonte
0

A dependência circular é também uma das razões para isso. [em geral]

Maor Dahan
fonte
0

Este é um erro que de alguma forma teve que depurar. Como já foi dito muitas vezes, a importação / exportação inadequada pode causar esse erro, mas surpreendentemente recebi esse erro de um pequeno bug no react-router-dom authentication setupmeu caso abaixo:

CONFIGURAÇÃO ERRADA:

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

CONFIGURAÇÃO CORRETA:

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

A única diferença era que eu estava desconstruindo o tokenno PrivateRoute component. A propósito, o token é obtido localstoragedessa const token = localStorage.getItem("authUser");forma, então se ele não estiver lá eu sei que o usuário não está autenticado. Isso também pode causar esse erro.

Lawrence Eagles
fonte
0

É muito simples, na verdade. Tive esse problema quando comecei a codificar o React, e o problema quase sempre é porque a importação:

import React, { memo } from 'react';

Você pode usar a desestruturação porque o react lib tem uma propriedade como memo, mas você não pode desestruturar algo assim

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

porque não é um objeto.

Espero que ajude!

Thuan Tran
fonte
0

React.Fragment

consertou o problema para mim

Erro de código:

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

Consertar

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

Não é necessário um problema direto relacionado à importação / exportação. No meu caso, eu estava renderizando um elemento filho dentro de um elemento pai e o elemento filho tem elemento / tag jsx que é usado, mas não importado. Eu importei e usei então ele consertou o problema. Portanto, o problema estava nos elementos jsx que estão dentro do elemento filho, NÃO na exportação do próprio elemento filho.

Tanaka
fonte
-1

Acabei de passar 30 minutos tentando resolver esse problema básico do BASIC.

Meu problema era que eu estava importando elementos nativos reac

por exemplo import React, { Text, Image, Component } from 'react';

E tentando usá-los, o que me levou a receber este erro.

Uma vez que eu mudar de <Text>para <p>e <Image>para <img>tudo funcionou como esperado.

Jacksonkr
fonte
-1

Eu estava recebendo este erro e nenhuma das respostas era meu caso, isso pode ajudar alguém a pesquisar:

Eu estava definindo um Proptype errado:

ids: PropTypes.array(PropTypes.string)

Deveria ser:

ids: PropTypes.arrayOf(PropTypes.string)

VSCode e o erro de compilação não me deram uma dica correta.

llessa
fonte
-2

EDITAR

Você está complexificando o processo. Basta fazer isso:

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
fonte
Tem certeza que o problema vem daqui? E não das próprias páginas?
John Smith,