Violação invariável: os objetos não são válidos como um filho de React

337

Na função de renderização do meu componente, tenho:

render() {
    const items = ['EN', 'IT', 'FR', 'GR', 'RU'].map((item) => {
      return (<li onClick={this.onItemClick.bind(this, item)} key={item}>{item}</li>);
    });
    return (
      <div>
        ...
                <ul>
                  {items}
                </ul>
         ...
      </div>
    );
  }

tudo fica bem, no entanto, ao clicar no <li>elemento, recebo o seguinte erro:

Erro não capturado: Violação invariável: os objetos não são válidos como um filho de React (encontrado: objeto com chaves {dispatchConfig, dispatchMarker, nativeEvent, target, currentTarget, tipo, eventPhase, bolhas, cancelável, timeStamp, defaultPrevented, isTrusted, exibição, detalhe, screenX , screenY, clientX, clientY, ctrlKey, shiftKey, altKey, metaKey, getModifierState, botão, botões, relatedTarget, pageX, pageY, isDefaultPrevented, isPropagationStopped, _dispatchListeners, _dispatchIDs}). Se você pretendia render uma coleção de filhos, use uma matriz ou agrupe o objeto usando createFragment (object) nos complementos do React. Verifique o método de renderização de Welcome.

Se eu mudar para this.onItemClick.bind(this, item)a (e) => onItemClick(e, item)dentro dos tudo funciona função de mapa como esperado.

Se alguém pudesse explicar o que estou fazendo de errado e explicar por que recebo esse erro, seria ótimo

ATUALIZAÇÃO 1: a
função onItemClick é a seguinte e a remoção de this.setState resulta no desaparecimento do erro.

onItemClick(e, item) {
    this.setState({
      lang: item,
    });
}

Mas não consigo remover esta linha, pois preciso atualizar o estado desse componente

almeynman
fonte
2
Então, como this.onItemClické implementado?
Zerkms 14/10/2015
@zerkms Obrigado por responder, atualizei a pergunta, e sim, parece que o problema está em this.setState (), mas por que isso gera esse erro? :(
almeynman 14/10/2015
Existe um erro de sintaxe em setState? Uma vírgula extra? Pode não corrigir o erro, mas apenas o encontrei.
Bhargav Ponnapalli
vírgula @bhargavponnapalli é uma questão de preferência, meus eslint me obriga a fazer isso, mas removê-lo não ajuda, obrigado pela resposta
almeynman
Eu recebi esse erro quando esqueci chaves entre uma variável que havia se tornado um objeto de estado da variável local depois de adicioná-lo ao estado no refator.
jamescampbell

Respostas:

398

Eu estava tendo esse erro e, por acaso, incluí um objeto no meu código JSX sem querer, que eu esperava ser um valor de string:

return (
    <BreadcrumbItem href={routeString}>
        {breadcrumbElement}
    </BreadcrumbItem>
)

breadcrumbElementcostumava ser uma string, mas devido a um refator havia se tornado um objeto. Infelizmente, a mensagem de erro do React não fez um bom trabalho ao me indicar a linha onde o problema existia. Eu tive que seguir meu rastreamento de pilha até voltar a reconhecer os "adereços" sendo passados ​​para um componente e, em seguida, encontrei o código incorreto.

Você precisará fazer referência a uma propriedade do objeto que é um valor de sequência ou converter o Objeto em uma representação de sequência que seja desejável. Uma opção pode ser JSON.stringifyse você realmente deseja ver o conteúdo do objeto.

Code Commander
fonte
13
Então, se você tem um objeto, como iria transformá-lo em algo desejável?
adinutzyc21
4
Você precisará fazer referência a uma propriedade do objeto que é um valor de sequência ou converter o Objeto em uma representação de sequência que seja desejável. Uma opção pode ser JSON.stringify se você realmente deseja ver o conteúdo do objeto.
Code Commander
2
Foi encontrado o mesmo erro e esta explicação resolveu meu problema. 1 UP para isso. :)
papski
Ah, tive o mesmo problema da mensagem de erro apontando para a linha errada - dizia que o erro estava neste.setState ({items: items}) quando realmente explodiu mais abaixo, onde eu estava tentando exibir essa variável usando { this.state.items}. JSON.stringify corrigiu isso!
RubberDuckRabbit
Para futuros leitores: Não, não converta para string. Faça isso: const Lcomponent = this.whateverReturnsObject (); então em renderizar () {return <Lcomponent />} é isso.
Nick
102

Então, eu recebi esse erro ao tentar exibir a createdAtpropriedade que é um objeto Date. Se você concatenar .toString()no final dessa maneira, ele fará a conversão e eliminará o erro. Basta postar isso como uma possível resposta, caso mais alguém tenha o mesmo problema:

{this.props.task.createdAt.toString()}
Brett84c
fonte
2
Bingo! Eu tive esse problema, mas fui jogado fora dos trilhos porque a tabela que estava sendo exibida carregava (e recarregava) muito bem. A reação só lançaria a objects are not validviolação invariável quando eu adicionasse uma linha. Acontece que eu estava convertendo o objeto Date () em uma string antes de persistir, para que apenas minhas novas linhas tivessem objetos para a data criada. :( Aprenda com o meu exemplo rebelde, pessoas! #
727 Steve #
37

Acabei de receber o mesmo erro, mas devido a um erro diferente: usei chaves duplas como:

{{count}}

para inserir o valor de em countvez do correto:

{count}

no qual o compilador provavelmente se transformou {{count: count}}, ou seja, tentando inserir um Objeto como um filho do React.

Dogbert
fonte
3
o {{}} são destinadas para /
Muneem Habib
4
@MuneemHabib é apenas a sintaxe do ES6. O React precisa de um par de {}. O par interno é tratado como código ES6. No ES6, {count}é o mesmo que {count: count}. Então, quando você digita {{count}}, é exatamente o mesmo que { {count: count} }.
Dogbert
1
Teve este erro - este foi o problema. Ao atribuir minha variável ao estado no construtor que eu tinha this.state = {navMenuItems: {navMenu}};... o que basicamente transformou meu JSX navMenuem um objeto genérico. Alterar para this.state = {navMenuItems: navMenu};se livrar do "elenco" não intencional Objecte corrigir o problema.
Lowcrawler 01/07/19
30

Só pensei em acrescentar isso porque eu tinha o mesmo problema hoje, acontece que era porque eu estava retornando apenas a função, quando a envolvi em uma <div>tag que começou a funcionar, como abaixo

renderGallery() {
  const gallerySection = galleries.map((gallery, i) => {
    return (
      <div>
        ...
      </div>
    );
  });
  return (
    {gallerySection}
  );
}

O exemplo acima causou o erro. Corrigi o problema alterando a return()seção para:

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

...ou simplesmente:

return gallerySection
user2997982
fonte
8
ou você pode simplesmente usar return gallerySectionse quiser evitar um extradiv
Vishal 11/11
5
Voltar em gallerySectionvez de <div>{gallerySection}</div>me ajudou.
Zanon
16

O filho da reação (singular) deve ser o tipo de dado primitivo, não o objeto, ou pode ser a tag JSX (que não é o nosso caso) . Use o pacote Proptypes no desenvolvimento para garantir que a validação ocorra.

Apenas uma rápida comparação de snippet de código (JSX) para representá-lo com uma ideia:

  1. Erro: com o objeto sendo passado para o filho

    <div>
    {/* item is object with user's name and its other details on it */}
     {items.map((item, index) => {
      return <div key={index}>
    --item object invalid as react child--->>>{item}</div>;
     })}
    </div>
  2. Sem erro: Com a propriedade do objeto ( que deve ser primitiva, ou seja, um valor de sequência ou valor inteiro ) sendo passado para filho.

    <div>
     {/* item is object with user's name and its other details on it */}
      {items.map((item, index) => {
       return <div key={index}>
    --note the name property is primitive--->{item.name}</div>;
      })}
    </div>

TLDR; (Na fonte abaixo): verifique se todos os itens que você está processando no JSX são primitivos e não objetos ao usar o React. Esse erro geralmente ocorre porque uma função envolvida no despacho de um evento recebeu um tipo de objeto inesperado (por exemplo, passar um objeto quando você deveria passar uma string) ou parte do JSX em seu componente não faz referência a um primitivo (por exemplo, this.props vs this.props.name).

Fonte - codingbismuth.com

Conheça Zaveri
fonte
2
esse link não funciona mais, no entanto, acho que a estrutura da sua resposta é a mais informativa no meu caso de uso. Esse erro é produzido em ambientes nativos da Web e de reação e geralmente ocorre como um erro do ciclo de vida ao tentar .map () uma matriz de objetos em um componente usando o ciclo de vida assíncrono. Me deparei com este fio enquanto estiver usando reagir nativa reagir nativo-scrollview
Mibbit
Que bom que você acha útil e obrigado por sinalizar o problema do link.
Conheça Zaveri
1
Isso me ajudou. Devolva uma propriedade em vez de um objeto:return <p>{item.whatever}</p>;
Chris
15

O meu tinha a ver com colocar desnecessariamente chaves em volta de uma variável contendo um elemento HTML dentro da instrução de retorno da função render (). Isso fez com que o React o tratasse como um objeto e não como um elemento.

render() {
  let element = (
    <div className="some-class">
      <span>Some text</span>
    </div>
  );

  return (
    {element}
  )
}

Depois de remover as chaves do elemento, o erro desapareceu e o elemento foi renderizado corretamente.

Liran H
fonte
Obrigado! Remova as chaves do elemento também funciona para mim!
Hua Zhang
12

A minha tinha a ver com o esquecimento das chaves em volta dos adereços sendo enviados para um componente de apresentação:

Antes:

const TypeAheadInput = (name, options, onChange, value, error) => {

Depois de

const TypeAheadInput = ({name, options, onChange, value, error}) => {
steveareeno
fonte
1
Meu problema era mais parecido com o seu, então a aplicação da sua solução me ajudou. +1 e obrigado!
M1gp0z 07/07/19
9

Eu também estava recebendo o erro "Os objetos não são válidos como um filho de reagir" e, para mim, a causa foi a chamada de uma função assíncrona no meu JSX. Ver abaixo.

class App extends React.Component {
    showHello = async () => {
        const response = await someAPI.get("/api/endpoint");

        // Even with response ignored in JSX below, this JSX is not immediately returned, 
        // causing "Objects are not valid as a React child" error.
        return (<div>Hello!</div>);
    }

    render() {
        return (
            <div>
                {this.showHello()}
            </div>
        );
    }
}

O que aprendi é que a renderização assíncrona não é suportada no React. A equipe do React está trabalhando em uma solução, conforme documentado aqui .

Ken A Collins
fonte
o que, em vez deve fazer é atualizar Estado como os dados vêm em, e depois processar os componentes usando valores de estado
mrwagaba
o que, em vez deve fazer é atualizar Estado como os dados vêm em, e depois processar os componentes usando valores de estado
mrwagaba
7

Para quem usa o Firebase com Android, isso só afeta o Android. Minha emulação do iOS ignora isso.

E como postado por Apoorv Bankey acima.

Qualquer coisa acima do Firebase V5.0.3, para Android, atm é um fracasso. Consertar:

npm i --save firebase@5.0.3

Confirmado várias vezes aqui https://github.com/firebase/firebase-js-sdk/issues/871

RedEarth
fonte
Para qualquer pessoa que tente a solução proposta por KNDheeraj abaixo, **** 1 down vote Se você estiver usando o Firebase algum dos arquivos do seu projeto. Em seguida, basta colocar a declaração de base de dados de importação no final !! Eu sei que isso parece loucura, mas tente !! **************** Eu tentei e esta não é uma solução para iOS, mas apenas para Android no Windows.
RedEarth 31/07
6

Eu também tenho o mesmo problema, mas meu erro é tão estúpido. Eu estava tentando acessar o objeto diretamente.

class App extends Component {
    state = {
        name:'xyz',
        age:10
    }
    render() {
        return (
            <div className="App">
                // this is what I am using which gives the error
                <p>I am inside the {state}.</p> 

                //Correct Way is

                <p>I am inside the {this.state.name}.</p> 
            </div>
        );
    }                                                                             

}
Nimmi Verma
fonte
4

Se, por algum motivo, você importou o firebase. Então tente correr npm i --save [email protected]. Isso ocorre porque o firebase quebra o react-native, portanto, a execução disso o corrigirá.

Apoorv Bankey
fonte
3

No meu caso, esqueci de retornar um elemento html da função render e estava retornando um objeto. O que fiz foi envolver apenas os itens com um elemento html - uma div simples, como abaixo

<ul>{items}</ul>

Shan
fonte
3

Eu tive o mesmo problema porque não coloquei o propsaparelho nos cílios.

export default function Hero(children, hero ) {
    return (
        <header className={hero}>
            {children}
        </header>
    );
}

Portanto, se seu código for semelhante ao código acima, você receberá esse erro. Para resolver isso, basta colocar chaves em volta do props.

export default function Hero({ children, hero }) {
    return (
        <header className={hero}>
            {children}
        </header>
    );
}
Suresh Mangs
fonte
@Dharman Penso que esta foi bem compreendida, mesmo antes de este pequeno recuo
Suresh Mang
Eu não disse que não era. Eu acho que sua resposta parece melhor com o recuo. Se você não concordar, sinta-se à vontade para revertê-lo.
Dharman
3

Eu recebi o mesmo erro, mudei isso

export default withAlert(Alerts)

para isso

export default withAlert()(Alerts).

Nas versões mais antigas, o código anterior estava ok, mas nas versões posteriores ele gera um erro. Portanto, use o código posterior para evitar o erro.

Shubham Patil
fonte
3

No meu caso, o erro estava acontecendo porque retornei a matriz de elementos entre chaves em vez de apenas retornar a própria matriz.

Código com erro

   render() {
        var rows = this.props.products.map(product => <tr key={product.id}><td>{product.name}</td><td>{product.price}</td></tr>
        );
        return {rows};
    }

Código correto

render() {
    var rows = this.props.products.map(product => <tr key={product.id}><td>{product.name}</td><td>{product.price}</td></tr>
    );
    return rows;
}
Namik Hajiyev
fonte
2

Você estava apenas usando as chaves do objeto, em vez de todo o objeto!

Mais detalhes podem ser encontrados aqui: https://github.com/gildata/RAIO/issues/48

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class SCT extends Component {
    constructor(props, context) {
        super(props, context);
        this.state = {
            data: this.props.data,
            new_data: {}
        };
    }
    componentDidMount() {
        let new_data = this.state.data;
        console.log(`new_data`, new_data);
        this.setState(
            {
                new_data: Object.assign({}, new_data)
            }
        )
    }
    render() {
        return (
            <div>
                this.state.data = {JSON.stringify(this.state.data)}
                <hr/>
                <div style={{color: 'red'}}>
                    {this.state.new_data.name}<br />
                    {this.state.new_data.description}<br />
                    {this.state.new_data.dependtables}<br />
                </div>
            </div>
        );
    }
}

SCT.propTypes = {
    test: PropTypes.string,
    data: PropTypes.object.isRequired
};

export {SCT};
export default SCT;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Cody Gray
fonte
2

Eu tenho o mesmo problema, no meu caso, atualizo o estado redux e os novos parâmetros de dados não correspondiam aos parâmetros antigos. Por isso, quando quero acessar alguns parâmetros através deste Erro,

Talvez essa experiência ajude alguém

Mohammad Masoumi
fonte
No meu caso, (Django) ListSerializer e CreateSerializer retornam os mesmos campos e alguns deles (depende do seu projeto) são apenas campos somente leitura, então busque uma vez e sempre que criar novos dados, basta atualizar o estado de redux
Mohammad Masoumi
2

Se você estiver usando o Firebase e vendo esse erro, vale a pena verificar se está importando corretamente. A partir da versão 5.0.4, você precisa importá-lo desta forma:

import firebase from '@firebase/app'
import '@firebase/auth';
import '@firebase/database';
import '@firebase/storage';

Sim eu conheço. Também perdi 45 minutos nisso.

Lucas Bustamante
fonte
Obrigado. Ele resolveu o meu problema com firebase (5.9.2) :)
Companheiro
2

Normalmente, isso aparece porque você não destrói corretamente. Veja este código, por exemplo:

const Button = text => <button>{text}</button>

const SomeForm = () => (
  <Button text="Save" />
)

Estamos declarando isso com o = text =>param. Mas, realmente, o React espera que este seja um propsobjeto abrangente .

Então, deveríamos realmente fazer algo parecido com isto:

const Button = props => <button>{props.text}</button>

const SomeForm = () => (
  <Button text="Save" />
)

Percebe a diferença? O propsparâmetro aqui pode ser chamado de qualquer coisa ( propsé apenas a convenção que corresponde à nomenclatura), React está apenas esperando um objeto com chaves e vals.

Com a destruição de objetos, você pode fazer e verá frequentemente algo como isto:

const Button = ({ text }) => <button>{text}</button>

const SomeForm = () => (
  <Button text="Save" />
)

... o que funciona.

As chances são de que qualquer um que tropeçar nisso acidentalmente tenha declarado parametricamente os suportes de seus componentes sem se desestruturar.

corysimmons
fonte
1

Acabei de me submeter a uma versão realmente boba desse erro, que também posso compartilhar aqui para a posteridade.

Eu tinha algum JSX assim:

...
{
  ...
  <Foo />
  ...
}
...

Eu precisava comentar isso para depurar alguma coisa. Eu usei o atalho de teclado no meu IDE, o que resultou nisso:

...
{
  ...
  { /* <Foo /> */ }
  ...
}
...

O que é, obviamente, inválido - objetos não são válidos como filhos reagentes!

shabs
fonte
1

Eu gostaria de adicionar outra solução a esta lista.

Especificações:

  • "reagir": "^ 16.2.0",
  • "react-dom": "^ 16.2.0",
  • "react-redux": "^ 5.0.6",
  • "scripts de reação": "^ 1.0.17",
  • "redux": "^ 3.7.2"

Eu encontrei o mesmo erro:

Erro não capturado: os objetos não são válidos como um filho do React (encontrado: objeto com as chaves {XXXXX}). Se você pretendia render uma coleção de filhos, use uma matriz.

Este foi o meu código:

let payload = {
      guess: this.userInput.value
};

this.props.dispatch(checkAnswer(payload));

Solução:

  // let payload = {
  //   guess: this.userInput.value
  // };

this.props.dispatch(checkAnswer(this.userInput.value));

O problema estava ocorrendo porque a carga útil estava enviando o item como um objeto. Quando removi a variável de carga útil e coloquei o valor userInput no despacho, tudo começou a funcionar como esperado.

bprdev
fonte
1

Se você estiver usando o Firebase, algum dos arquivos do seu projeto. Em seguida, basta colocar a declaração de base de dados de importação no final !!

Eu sei que isso parece loucura, mas tente !!

KNDheeraj
fonte
1

Meu problema foi simples quando enfrentei o seguinte erro:

objects are not valid as a react child (found object with keys {...}

foi só que eu estava passando um objeto com as chaves especificadas no erro enquanto tentava renderizar o objeto diretamente em um componente usando {object} esperando que fosse uma string

object: {
    key1: "key1",
    key2: "key2"
}

durante a renderização em um componente React, usei algo como abaixo

render() {
    return this.props.object;
}

mas deveria ter sido

render() {
    return this.props.object.key1;
}
kaushalop
fonte
1

Se estiver usando componentes sem estado, siga este tipo de formato:

const Header = ({pageTitle}) => (
  <h1>{pageTitle}</h1>
);
export {Header};

Isso pareceu funcionar para mim

ppak10
fonte
1

Algo assim aconteceu comigo ...

Eu escrevi:

{response.isDisplayOptions &&
{element}
}

Colocá-lo dentro de uma div corrigiu:

{response.isDisplayOptions &&
    <div>
        {element}
    </div>
}
Oranit Dar
fonte
1

Encontrado: objeto com chaves

O que significa que passar algo é um valor-chave. Então, você precisa modificar seu manipulador:

de
onItemClick(e, item) {
   this.setState({
     lang: item,
   });
}
para
onItemClick({e, item}) {
  this.setState({
    lang: item,
  });
}

Você perdeu o aparelho ( {}).

Arul Mani
fonte
1
Não posso acreditar que este era o problema
kushal.8
Eu também me pergunto. ainda não descobri qual é o problema que causa isso
Arul Mani 07/01
1

No meu caso, adicionei uma assíncrona ao meu componente de função filho e encontrei esse erro. Não use assíncrono com componente filho.

tolga
fonte
0

No caso de usar o Firebase, se não funcionar colocando no final das importinstruções, você pode tentar colocar isso dentro de um dos métodos do ciclo de vida, ou seja, você pode colocá-lo dentro componentWillMount().

componentWillMount() {
    const firebase = require('firebase');
    firebase.initializeApp({
        //Credentials
    });
}
Germa Vinsmoke
fonte
0

Invariant Violation: Objects are not valid as a React childaconteceu comigo ao usar um componente que precisava de renderItemadereços, como:

renderItem={this.renderItem}

e meu erro foi fazer o meu renderItemmétodo async.

vmarquet
fonte
0

Meu erro foi devido a escrevê-lo desta maneira:

props.allinfo.map((stuff, i)=>{
  return (<p key={i}> I am {stuff} </p>)
})



ao invés de:

props.allinfo.map((stuff, i)=>{
  return (<p key={i}> I am {stuff.name} </p>)
})

Isso significava que eu estava tentando renderizar um objeto em vez do valor dentro dele.

editar: isto é para reagir não nativo.

Deke
fonte