Infracción invariable: los objetos no son válidos como React child

337

En la función de render de mi componente tengo:

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

todo funciona bien, sin embargo, al hacer clic en el <li>elemento, recibo el siguiente error:

Error no detectado: Infracción invariable: los objetos no son válidos como React child (encontrado: objeto con claves {dispatchConfig, dispatchMarker, nativeEvent, target, currentTarget, type, eventPhase, bubbles, cancelable, timeStamp, defaultPrevented, isTrusted, view, detail, screenX , screenY, clientX, clientY, ctrlKey, shiftKey, altKey, metaKey, getModifierState, button, buttons, relatedTarget, pageX, pageY, isDefaultPrevented, isPropagationStopped, _dispatchListeners, _dispatchIDs}). Si tenía la intención de representar una colección de elementos secundarios, use una matriz en su lugar o ajuste el objeto usando createFragment (objeto) de los complementos React. Verifique el método de renderizado de Welcome.

Si cambio a this.onItemClick.bind(this, item)que (e) => onItemClick(e, item)dentro de las funciones todo funciona como se esperaba mapa.

Si alguien pudiera explicar lo que estoy haciendo mal y explicar por qué recibo este error, sería genial

ACTUALIZACIÓN 1: la
función onItemClick es la siguiente y al eliminar this.setState se produce la desaparición del error.

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

Pero no puedo eliminar esta línea ya que necesito actualizar el estado de este componente

almeynman
fuente
2
Entonces, ¿cómo this.onItemClickse implementa?
zerkms
@zerkms Gracias por responder, actualicé la pregunta y sí, parece que el problema está en this.setState (), pero ¿por qué arroja este error? :(
almeynman
¿Hay un error de sintaxis en setState? ¿Una coma extra? Puede que no solucione el error, pero lo encontré.
Bhargav Ponnapalli
La coma de @bhargavponnapalli es una cuestión de preferencia, mi eslint me obliga a hacerlo, pero eliminarlo no ayuda, gracias por responder
almeynman
Recibí este error cuando olvidé las llaves alrededor de una variable que se había convertido en un objeto con estado de la variable local después de agregarlo al estado en refactor.
jamescampbell

Respuestas:

398

Estaba teniendo este error y resultó que estaba incluyendo involuntariamente un objeto en mi código JSX que esperaba que fuera un valor de cadena:

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

breadcrumbElementsolía ser una cadena pero debido a un refactor se había convertido en un Objeto. Desafortunadamente, el mensaje de error de React no hizo un buen trabajo al señalarme la línea donde existía el problema. Tuve que seguir mi rastro de la pila hasta que reconocí los "accesorios" que se pasaban a un componente y luego encontré el código ofensivo.

Deberá hacer referencia a una propiedad del objeto que sea un valor de cadena o convertir el Objeto en una representación de cadena que sea deseable. Una opción podría ser JSON.stringifysi realmente desea ver el contenido del Objeto.

Code Commander
fuente
13
Entonces, si tienes un objeto, ¿cómo harías para transformarlo en algo deseable?
adinutzyc21
44
Deberá hacer referencia a una propiedad del objeto que sea un valor de cadena o convertir el Objeto en una representación de cadena que sea deseable. Una opción podría ser JSON.stringify si realmente desea ver el contenido del Objeto.
Code Commander
2
Encontré el mismo error y esta explicación resolvió mi problema. 1 UP por esto. :)
papski el
Ahh, tuve el mismo problema con el mensaje de error que apuntaba a la línea incorrecta: decía que el error estaba en this.setState ({items: items}) cuando realmente explotó más abajo donde estaba tratando de mostrar esa variable usando { this.state.items}. JSON.stringify lo arregló!
RubberDuckRabbit
Para futuros lectores: No, no convertir a cadena. Haga esto en su lugar: const Lcomponent = this.whateverReturnsObject (); luego en render () {return <Lcomponent />} Eso es su.
Nick
102

Entonces recibí este error al intentar mostrar la createdAtpropiedad que es un objeto Date. Si concatena .toString()al final de esta manera, hará la conversión y eliminará el error. Simplemente publique esto como una posible respuesta en caso de que alguien más se encuentre con el mismo problema:

{this.props.task.createdAt.toString()}
Brett84c
fuente
2
¡Bingo! Tuve este problema, pero me desvié porque la tabla que lo mostraba se cargaría (y volvería a cargar) bien. Reaccionar solo arrojaría la objects are not validviolación invariante cuando agregue una fila. Resulta que estaba convirtiendo el objeto Date () en una cadena antes de persistir, por lo que solo mis nuevas filas tenían objetos para la fecha creada. :( ¡Aprenda de mi ejemplo de personas rebeldes!
Steve
37

Acabo de recibir el mismo error pero debido a un error diferente: utilicé llaves dobles como:

{{count}}

para insertar el valor de en countlugar del correcto:

{count}

en el que presumiblemente se convirtió el compilador {{count: count}}, es decir, tratando de insertar un objeto como un hijo React

Dogbert
fuente
3
para qué {{}} están destinados /
Muneem Habib
44
@MuneemHabib es solo la sintaxis de ES6. React necesita un par de {}. El par interno se trata como código ES6. En ES6, {count}es lo mismo que {count: count}. Entonces, cuando escribe {{count}}, eso es exactamente lo mismo que { {count: count} }.
Dogbert el
1
Tenía este error, este era el problema. Al asignar mi variable al estado en el constructor que tenía this.state = {navMenuItems: {navMenu}};... que básicamente convirtió mi JSX navMenuen un objeto genérico. Cambiando para this.state = {navMenuItems: navMenu};deshacerse del 'elenco' involuntario Objecty solucionado el problema.
lowcrawler 01 de
30

Solo pensé que agregaría a esto ya que tenía el mismo problema hoy, resulta que fue porque estaba devolviendo solo la función, cuando lo envolví en una <div>etiqueta comenzó a funcionar, como se muestra a continuación

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

Lo anterior causó el error. Solucioné el problema cambiando la return()sección a:

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

...o simplemente:

return gallerySection
usuario2997982
fuente
8
o simplemente puede usar return gallerySectionsi desea evitar un extradiv
Vishal
55
Regresar en gallerySectionlugar de <div>{gallerySection}</div>ayudarme.
Zanon el
16

React child (singular) debe ser un tipo de datos primitivos , no un objeto o podría ser una etiqueta JSX (que no es nuestro caso) . Utilice el paquete Proptypes en desarrollo para asegurarse de que se realice la validación.

Solo una comparación rápida de fragmentos de código (JSX) para representarlo con una idea:

  1. Error: con el objeto que se pasa al niño

    <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. Sin error: con la propiedad del objeto ( que debe ser primitiva, es decir, un valor de cadena o valor entero ) que se pasa al hijo.

    <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; (De la fuente a continuación): asegúrese de que todos los elementos que está renderizando en JSX son primitivos y no objetos al usar React. Este error generalmente ocurre porque a una función involucrada en el envío de un evento se le ha dado un tipo de objeto inesperado (es decir, pasar un objeto cuando debería pasar una cadena) o parte de JSX en su componente no hace referencia a una primitiva (es decir, this.props vs this.props.name).

Fuente - codingbismuth.com

Conoce a Zaveri
fuente
2
este enlace ya no funciona, sin embargo, creo que la estructura de su respuesta es la más informativa en mi caso de uso. Este error se puede producir tanto en entornos web como en entornos nativos de reacción, y a menudo se produce como un error del ciclo de vida cuando se intenta .map () una matriz de objetos dentro de un componente que utiliza el ciclo de vida asíncrono. Me encontré con este hilo al usar react native react-native-scrollview
mibbit
Me alegro de que lo encuentre útil y gracias por marcar el problema del enlace.
Conoce a Zaveri el
1
Esto me ayudo. Devolver una propiedad en lugar de un objeto:return <p>{item.whatever}</p>;
Chris
15

El mío tenía que ver con poner innecesariamente llaves alrededor de una variable que contenía un elemento HTML dentro de la declaración de retorno de la función render (). Esto hizo que React lo tratara como un objeto en lugar de un elemento.

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

  return (
    {element}
  )
}

Una vez que quité las llaves del elemento, el error desapareció y el elemento se procesó correctamente.

Liran H
fuente
¡Gracias! ¡Quitar las llaves del elemento también me funciona!
Hua Zhang el
12

El mío tuvo que ver con olvidar las llaves entre los accesorios que se envían a un componente de presentación:

Antes de:

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

Después

const TypeAheadInput = ({name, options, onChange, value, error}) => {
steveareeno
fuente
1
Mi problema era más similar al tuyo, por lo que la aplicación de tu solución me ayudó. +1 y gracias!
m1gp0z
9

Yo también recibí este error "Los objetos no son válidos como React child" y para mí la causa se debió a llamar a una función asincrónica en mi JSX. Vea abajo.

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

Lo que aprendí es que la representación asincrónica no es compatible con React. El equipo de React está trabajando en una solución como se documenta aquí .

Ken A Collins
fuente
lo que en su lugar debe hacer es actualizar el estado como los datos entra, y luego hacer que los componentes utilizando los valores de estado
mrwagaba
lo que en su lugar debe hacer es actualizar el estado como los datos entra, y luego hacer que los componentes utilizando los valores de estado
mrwagaba
7

Para cualquiera que use Firebase con Android, esto solo rompe Android. Mi emulación de iOS lo ignora.

Y según lo publicado por Apoorv Bankey arriba.

Cualquier cosa por encima de Firebase V5.0.3, para Android, atm es un fracaso. Reparar:

npm i --save firebase@5.0.3

Confirmado numerosas veces aquí https://github.com/firebase/firebase-js-sdk/issues/871

Tierra roja
fuente
Para cualquiera que intente la solución propuesta por KNDheeraj a continuación, **** 1 voto negativo en caso de que esté usando Firebase cualquiera de los archivos dentro de su proyecto. ¡Entonces solo coloca esa declaración de importación de Firebase al final! Sé que esto suena loco pero ¡pruébalo! **************** Lo intenté y esta no es una solución para iOS, sino solo para Android en Windows.
RedEarth
6

También tengo el mismo problema pero mi error es tan estúpido. Estaba tratando de acceder al objeto directamente.

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
fuente
4

Si por alguna razón importó firebase. Entonces intenta correr npm i --save [email protected]. Esto se debe a que Firebase rompe react-native, por lo que ejecutar esto lo solucionará.

Apoorv Bankey
fuente
3

En mi caso, se me olvidó devolver un elemento html de la función render y estaba devolviendo un objeto. Lo que hice fue envolver los {items} con un elemento html, un div simple como el siguiente

<ul>{items}</ul>

Shan
fuente
3

Tuve el mismo problema porque no puse las propsllaves.

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

Entonces, si su código es similar al anterior, obtendrá este error. Para resolver esto, simplemente coloque llaves alrededor del props.

export default function Hero({ children, hero }) {
    return (
        <header className={hero}>
            {children}
        </header>
    );
}
Suresh Mangs
fuente
@Dharman Creo que esto se entendió bien incluso antes de esta pequeña sangría
Suresh Mangs
No dije que no lo fuera. Creo que su respuesta se ve mejor con la sangría. Si no está de acuerdo, no dude en revertirlo.
Dharman el
3

Recibí el mismo error, cambié esto

export default withAlert(Alerts)

a esto

export default withAlert()(Alerts).

En versiones anteriores, el código anterior estaba bien, pero en versiones posteriores arroja un error. Entonces use el código posterior para evitar el error.

Shubham Patil
fuente
3

En mi caso, el error estaba ocurriendo porque devolví la matriz de elementos entre llaves lugar de simplemente devolver la matriz en sí.

Código con error

   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 correcto

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
fuente
2

¡Solo estabas usando las teclas de objeto, en lugar de todo el objeto!

Puede encontrar más detalles aquí: 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
fuente
2

Tengo el mismo problema, en mi caso, actualizo el estado redux , y los nuevos parámetros de datos no coincidían con los parámetros antiguos, así que cuando quiero acceder a algunos parámetros a través de este Error,

Quizás esta experiencia ayude a alguien

Mohammad Masoumi
fuente
En mi caso, (Django) ListSerializer y CreateSerializer devuelven los mismos campos y algunos de ellos (depende de su proyecto) son solo campos de solo lectura, así que busque una vez y cada vez que cree datos nuevos, simplemente actualice el estado redux
Mohammad Masoumi
2

Si está utilizando Firebase y ve este error, vale la pena verificar si lo está importando correctamente. A partir de la versión 5.0.4, debe importarlo así:

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

Sí, lo sé. También perdí 45 minutos en esto.

Lucas Bustamante
fuente
Gracias. Resolvió mi problema con firebase (5.9.2) :)
Mate
2

Por lo general, esto aparece porque no se desestructura correctamente. Tome este código por ejemplo:

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

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

Lo estamos declarando con el = text =>param. Pero en realidad, React espera que este sea un propsobjeto que lo abarque todo .

Entonces realmente deberíamos estar haciendo algo como esto:

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

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

¿Nota la diferencia? El propsparámetro aquí podría llamarse cualquier cosa ( propses solo la convención que coincide con la nomenclatura), React solo espera un objeto con claves y valles.

Con la desestructuración de objetos puede hacer, y verá con frecuencia, algo como esto:

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

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

... que funciona.

Lo más probable es que cualquiera que se tope con esto simplemente haya declarado accidentalmente los accesorios de sus componentes param sin desestructuración.

corysimmons
fuente
1

Acabo de pasar por una versión realmente tonta de este error, que también podría compartir aquí para la posteridad.

Tuve algunos JSX como este:

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

Necesitaba comentar esto para depurar algo. Usé el atajo de teclado en mi IDE, lo que resultó en esto:

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

Lo cual, por supuesto, no es válido: ¡los objetos no son válidos como hijos secundarios!

shabs
fuente
1

Me gustaría agregar otra solución a esta lista.

Especificaciones:

  • "reaccionar": "^ 16.2.0",
  • "react-dom": "^ 16.2.0",
  • "react-redux": "^ 5.0.6",
  • "react-scripts": "^ 1.0.17",
  • "redux": "^ 3.7.2"

Encontré el mismo error:

Error no detectado: los objetos no son válidos como React child (encontrado: objeto con claves {XXXXX}). Si desea representar una colección de elementos secundarios, utilice una matriz en su lugar.

Este fue mi código:

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

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

Solución:

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

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

El problema estaba ocurriendo porque la carga útil estaba enviando el artículo como un objeto. Cuando eliminé la variable de carga útil y puse el valor de entrada de usuario en el despacho, todo comenzó a funcionar como se esperaba.

bprdev
fuente
1

En caso de que esté usando Firebase cualquiera de los archivos dentro de su proyecto. ¡Entonces solo coloca esa declaración de importación de Firebase al final!

Sé que esto suena loco pero ¡pruébalo!

KNDheeraj
fuente
1

Mi problema fue simple cuando me enfrenté al siguiente error:

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

era solo que estaba pasando un objeto con las claves especificadas en el error mientras intentaba representar el objeto directamente en un componente usando {object} esperando que fuera una cadena

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

mientras renderizaba en un componente React, usé algo como a continuación

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

pero debería haber sido

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

Si usa componentes sin estado, siga este tipo de formato:

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

Esto pareció funcionar para mí.

ppak10
fuente
1

Algo como esto me acaba de pasar ...

Escribí:

{response.isDisplayOptions &&
{element}
}

Colocándolo dentro de un div lo arregló:

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

Encontrado: objeto con claves

Lo que significa que pasar algo es un valor clave. Por lo tanto, debe modificar su controlador:

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

Te perdiste las llaves ( {}).

Arul Mani
fuente
1
no puedo creer que este fuera el problema
kushal.8
También me pregunto. todavía no he descubierto qué problema es lo que causa esto
Arul Mani
1

En mi caso, agregué un asíncrono a mi componente de función hijo y encontré este error. No use asíncrono con el componente hijo.

Tolga
fuente
0

En el caso de usar Firebase, si no funciona colocando al final de las importdeclaraciones, puede intentar poner eso dentro de uno de los métodos del ciclo de vida, es decir, puede ponerlo dentro componentWillMount().

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

Invariant Violation: Objects are not valid as a React childme pasó cuando usé un componente que necesitaba renderItemaccesorios, como:

renderItem={this.renderItem}

y mi error fue hacer mi renderItemmétodo async.

vmarquet
fuente
0

Mi error fue por escribirlo de esta manera:

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



en vez de:

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

Significaba que estaba tratando de representar el objeto en lugar del valor dentro de él.

editar: esto es para reaccionar no nativo.

Deke
fuente