Violation invariante: les objets ne sont pas valides en tant qu'enfant React

337

Dans la fonction de rendu de mon composant, j'ai:

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

tout se passe bien, cependant en cliquant sur le <li> élément, je reçois l'erreur suivante:

Erreur non détectée: violation invariante: les objets ne sont pas valides en tant qu'enfant React (trouvé: objet avec clés {dispatchConfig, dispatchMarker, nativeEvent, target, currentTarget, type, eventPhase, bubble, cancelable, timeStamp, defaultPrevented, isTrusted, view, detail, screenX , screenY, clientX, clientY, ctrlKey, shiftKey, altKey, metaKey, getModifierState, bouton, boutons, relatedTarget, pageX, pageY, isDefaultPrevented, isPropagationStopped, _dispatchListeners, _dispatchIDs}). Si vous vouliez rendre une collection d'enfants, utilisez plutôt un tableau ou encapsulez l'objet à l'aide de createFragment (objet) à partir des modules complémentaires React. Vérifiez la méthode de rendu deWelcome .

Si je change pour this.onItemClick.bind(this, item) à l' (e) => onItemClick(e, item)intérieur de la fonction de carte tout fonctionne comme prévu.

Si quelqu'un pouvait expliquer ce que je fais mal et expliquer pourquoi j'obtiens cette erreur, ce serait bien

MISE À JOUR 1: la
fonction onItemClick est la suivante et la suppression de this.setState entraîne la disparition de l'erreur.

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

Mais je ne peux pas supprimer cette ligne car j'ai besoin de mettre à jour l'état de ce composant

almeynman
la source
2
Alors, comment this.onItemClickest mis en œuvre?
zerkms
@zerkms Merci d'avoir répondu, j'ai mis à jour la question, et oui, il semble que le problème se trouve dans this.setState (), mais pourquoi renvoie-t-il cette erreur? :(
almeynman
Y a-t-il une erreur de syntaxe dans setState? Une virgule supplémentaire? Pourrait ne pas corriger l'erreur, mais vient de la trouver.
Bhargav Ponnapalli
La virgule @bhargavponnapalli est une question de préférence, mon eslint me force à le faire, mais le supprimer n'aide pas, merci pour la réponse
almeynman
J'ai eu cette erreur lorsque j'ai oublié des accolades autour d'une variable qui était devenue un objet d'état à partir d'une variable locale après l'avoir ajoutée à l'état dans refactor.
jamescampbell

Réponses:

398

J'avais cette erreur et il s'est avéré que j'incluais involontairement un objet dans mon code JSX que je m'attendais à être une valeur de chaîne:

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

breadcrumbElementutilisé pour être une chaîne, mais en raison d'un refactor est devenu un objet. Malheureusement, le message d'erreur de React n'a pas fait du bon travail en me pointant vers la ligne où le problème existait. J'ai dû suivre ma trace de pile tout le long du chemin jusqu'à ce que je reconnaisse les «accessoires» transmis à un composant, puis j'ai trouvé le code incriminé.

Vous devrez soit référencer une propriété de l'objet qui est une valeur de chaîne, soit convertir l'objet en une représentation de chaîne souhaitable. Une option pourrait être JSON.stringifysi vous voulez réellement voir le contenu de l'objet.

Commandant de code
la source
13
Donc, si vous avez un objet, comment allez-vous le transformer en quelque chose de souhaitable?
adinutzyc21
4
Vous devrez soit référencer une propriété de l'objet qui est une valeur de chaîne, soit convertir l'objet en une représentation de chaîne souhaitable. Une option peut être JSON.stringify si vous voulez réellement voir le contenu de l'objet.
Code Commander
2
J'ai rencontré la même erreur et cette explication a résolu mon problème. 1 UP pour cela. :)
papski
Ahh, j'ai eu le même problème de message d'erreur pointant vers la mauvaise ligne - il a dit que l'erreur était dans this.setState ({items: items}) quand vraiment il a explosé plus bas où j'essayais d'afficher cette variable en utilisant { this.state.items}. JSON.stringify l'a corrigé!
RubberDuckRabbit
Pour les futurs lecteurs: Non, ne convertissez pas en chaîne. Faites ceci à la place: const Lcomponent = this.wwhatReturnsObject (); puis dans render () {return <Lcomponent />} C'est son.
Nick
102

J'ai donc eu cette erreur en essayant d'afficher la createdAtpropriété qui est un objet Date. Si vous concaténez .toString()à la fin comme ceci, il fera la conversion et éliminera l'erreur. Il suffit de poster ceci comme une réponse possible au cas où quelqu'un d'autre rencontrerait le même problème:

{this.props.task.createdAt.toString()}
Brett84c
la source
2
Bingo! J'ai eu ce problème mais j'ai été éjecté parce que la table qui l'affichait se chargeait (et se rechargeait) très bien. React ne lancerait la objects are not validviolation invariante que lorsque j'ajouterais une ligne. Il s'avère que je convertissais l'objet Date () en une chaîne avant de le persister, donc seules mes nouvelles lignes avaient des objets pour la date créée. :( Apprenez de mes exemples capricieux!
Steve
37

Je viens de recevoir la même erreur mais en raison d'une erreur différente: j'ai utilisé des accolades doubles comme:

{{count}}

pour insérer la valeur de countau lieu de la bonne:

{count}

dans lequel le compilateur s'est vraisemblablement transformé {{count: count}}, c'est-à-dire en essayant d'insérer un objet en tant qu'enfant React.

Dogbert
la source
3
à quoi {{}} sont destinés /
Muneem Habib
4
@MuneemHabib c'est juste la syntaxe ES6. React a besoin d'une paire de {}. La paire intérieure est traitée comme du code ES6. Dans ES6, {count}est identique à {count: count}. Ainsi, lorsque vous tapez {{count}}, c'est exactement la même chose que { {count: count} }.
Dogbert
1
Eu cette erreur - c'était le problème. En affectant ma variable à l'état dans le constructeur que j'avais this.state = {navMenuItems: {navMenu}};... ce qui a essentiellement transformé mon JSX navMenuen un objet générique. Changer pour this.state = {navMenuItems: navMenu};se débarrasser de la «distribution» involontaire Objectet résoudre le problème.
lowcrawler
30

J'ai pensé que j'allais ajouter à cela car j'avais le même problème aujourd'hui, il s'avère que c'était parce que je retournais juste la fonction, quand je l'ai enveloppée dans une <div>balise, elle a commencé à fonctionner, comme ci-dessous

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

Ce qui précède a provoqué l'erreur. J'ai résolu le problème en changeant la return()section en:

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

...ou simplement:

return gallerySection
user2997982
la source
8
ou vous pouvez simplement utiliser return gallerySectionsi vous voulez éviter un supplémentdiv
Vishal
5
Revenir gallerySectionau lieu de <div>{gallerySection}</div>m'a aidé.
Zanon
16

React child (singulier) doit être un type de type de données primitif et non un objet ou il peut s'agir d'une balise JSX (ce qui n'est pas le cas dans notre cas) . Utilisez le package Proptypes en développement pour vous assurer que la validation a lieu.

Juste une comparaison rapide d'extrait de code (JSX) pour vous représenter avec idée:

  1. Erreur: avec un objet transmis à l'enfant

    <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. Sans erreur: avec la propriété de l'objet ( qui doit être primitive, c'est-à-dire une valeur de chaîne ou une valeur entière ) transmise à l'enfant.

    <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 source ci-dessous): Assurez-vous que tous les éléments que vous effectuez dans JSX sont des primitives et non des objets lorsque vous utilisez React. Cette erreur se produit généralement car une fonction impliquée dans la répartition d'un événement a reçu un type d'objet inattendu (c'est-à-dire passer un objet alors que vous devriez passer une chaîne) ou une partie du JSX dans votre composant ne fait pas référence à une primitive (c'est-à-dire this.props vs this.props.name).

Source - codingbismuth.com

Rencontrez Zaveri
la source
2
ce lien ne fonctionne plus, mais je trouve que la structure de votre réponse est la plus informative dans mon cas d'utilisation. Cette erreur peut être produite dans les environnements Web natifs et réactifs, et se produit souvent sous la forme d'une erreur de cycle de vie lorsque vous tentez de .map () un tableau d'objets dans un composant à l'aide du cycle de vie asynchrone. Je suis tombé sur ce sujet lors de l'utilisation de react native react-native-scrollview
mibbit
Heureux que vous le trouviez utile et merci d'avoir signalé un problème de lien.
Rencontrez Zaveri le
1
Cela m'a aidé. Rendre une propriété plutôt qu'un objet:return <p>{item.whatever}</p>;
Chris
15

Le mien avait à voir avec la mise inutilement d'accolades autour d'une variable contenant un élément HTML à l'intérieur de l'instruction return de la fonction render (). Cela a amené React à le traiter comme un objet plutôt que comme un élément.

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

  return (
    {element}
  )
}

Une fois que j'ai supprimé les accolades de l'élément, l'erreur a disparu et l'élément a été rendu correctement.

Liran H
la source
Merci! Supprimer les accolades bouclées de l'élément fonctionne aussi pour moi!
Hua Zhang
12

Le mien avait à voir avec l'oubli des accolades autour des accessoires envoyés à un composant de présentation:

Avant:

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

Après

const TypeAheadInput = ({name, options, onChange, value, error}) => {
steveareeno
la source
1
Mon problème était le plus similaire au vôtre, alors l'application de votre solution m'a aidé. +1 et merci!
m1gp0z
9

Moi aussi, j'obtenais cette erreur «Les objets ne sont pas valides en tant qu'enfant React» et pour moi, la cause était due à l'appel d'une fonction asynchrone dans mon JSX. Voir ci-dessous.

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

Ce que j'ai appris, c'est que le rendu asynchrone n'est pas pris en charge dans React. L'équipe React travaille sur une solution telle que documentée ici .

Ken A Collins
la source
ce que vous devez plutôt faire est de mettre à jour l'état au fur et à mesure que les données arrivent, puis de rendre les composants à l'aide des valeurs d'état
mrwagaba
ce que vous devez plutôt faire est de mettre à jour l'état au fur et à mesure que les données arrivent, puis de rendre les composants à l'aide des valeurs d'état
mrwagaba
7

Pour toute personne utilisant Firebase avec Android, cela ne fait que casser Android. Mon émulation iOS l'ignore.

Et comme indiqué par Apoorv Bankey ci-dessus.

Tout ce qui est supérieur à Firebase V5.0.3, pour Android, atm est un buste. Réparer:

npm i --save firebase@5.0.3

Confirmé plusieurs fois ici https://github.com/firebase/firebase-js-sdk/issues/871

Terre rouge
la source
Pour tous ceux qui tentent la solution proposée par KNDheeraj ci-dessous, **** 1 vote négatif Si vous utilisez Firebase l'un des fichiers de votre projet. Ensuite, placez simplement cette déclaration d'importation Firebase à la fin !! Je sais que cela semble fou, mais essayez-le !! **************** Je l'ai essayé et ce n'est pas une solution pour iOS mais pour Android sur Windows uniquement.
RedEarth
6

J'ai aussi le même problème mais mon erreur est tellement stupide. J'essayais d'accéder directement à l'objet.

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
la source
4

Si, pour une raison quelconque, vous avez importé Firebase. Essayez ensuite de courir npm i --save [email protected]. Cela est dû au fait que Firebase Break réagit nativement, donc l'exécuter résoudra le problème.

Apoorv Bankey
la source
3

Dans mon cas, j'ai oublié de renvoyer un élément html dans la fonction de rendu et je retournais un objet. Ce que j'ai fait, c'est que j'ai simplement enveloppé les {items} avec un élément html - une simple div comme ci-dessous

<ul>{items}</ul>

Shan
la source
3

J'ai eu le même problème parce que je n'ai pas mis les propsaccolades.

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

Donc, si votre code est similaire à celui ci-dessus, vous obtiendrez cette erreur. Pour résoudre ce problème, placez simplement des accolades autour du props.

export default function Hero({ children, hero }) {
    return (
        <header className={hero}>
            {children}
        </header>
    );
}
Suresh Mangs
la source
@Dharman Je pense que cela était bien compris avant même cette petite indentation
Suresh Mangs
Je n'ai pas dit que ce n'était pas le cas. Je pense que votre réponse semble meilleure avec l'indentation. Si vous n'êtes pas d'accord, n'hésitez pas à revenir en arrière.
Dharman
3

J'ai la même erreur, j'ai changé ça

export default withAlert(Alerts)

pour ça

export default withAlert()(Alerts).

Dans les anciennes versions, l'ancien code était correct, mais dans les versions ultérieures, il génère une erreur. Utilisez donc le code ultérieur pour éviter l'erreur.

Shubham Patil
la source
3

Dans mon cas, l'erreur s'est produite car j'ai renvoyé un tableau d'éléments entre accolades au lieu de simplement renvoyer le tableau lui-même.

Code avec erreur

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

Code correct

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
la source
2

Vous utilisiez simplement les clés de l'objet, au lieu de l'objet entier!

Plus de détails peuvent être trouvés ici: 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
la source
2

J'ai le même problème, dans mon cas, je mets à jour le redux état et les nouveaux paramètres de données ne correspondent pas aux anciens paramètres, donc quand je veux accéder à certains paramètres via cette erreur,

Peut-être que cette expérience aide quelqu'un

Mohammad Masoumi
la source
Dans mon cas, (Django) ListSerializer et CreateSerializer retournent les mêmes champs et certains d'entre eux (c'est à votre projet) ne sont que des champs en lecture seule, alors récupérez une fois et créez de nouvelles données simplement mettez à jour l'état redux
Mohammad Masoumi
2

Si vous utilisez Firebase et voyez cette erreur, il vaut la peine de vérifier si vous l'importez correctement. Depuis la version 5.0.4, vous devez l'importer comme ceci:

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

Oui je sais. J'ai perdu 45 minutes là-dessus aussi.

Lucas Bustamante
la source
Je vous remercie. Cela a résolu mon problème avec Firebase (5.9.2) :)
Mate
2

En général, cela apparaît parce que vous ne détruisez pas correctement. Prenez ce code par exemple:

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

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

Nous le = text =>déclarons avec le param. Mais vraiment, React s'attend à ce que ce soit un propsobjet englobant .

Donc, nous devrions vraiment faire quelque chose comme ça:

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

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

Remarquez la différence? Le propsparamètre ici pourrait être nommé n'importe quoi (props c'est juste la convention qui correspond à la nomenclature), React attend juste un objet avec des clés et des valeurs.

Avec la déstructuration d'objets, vous pouvez faire et verrez souvent quelque chose comme ceci:

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

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

... qui fonctionne.

Il y a de fortes chances que quiconque tombe sur ce point ait déclaré accidentellement les accessoires de ses composants sans les déstructurer.

corysimmons
la source
1

Je viens de me mettre à travers une version vraiment stupide de cette erreur, que je pourrais aussi partager ici pour la postérité.

J'ai eu du JSX comme ça:

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

J'avais besoin de commenter cela pour déboguer quelque chose. J'ai utilisé le raccourci clavier dans mon IDE, ce qui a abouti à ceci:

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

Ce qui est, bien sûr, invalide - les objets ne sont pas valides comme réagissent les enfants!

shabs
la source
1

Je voudrais ajouter une autre solution à cette liste.

Spécifications:

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

J'ai rencontré la même erreur:

Erreur non interceptée: les objets ne sont pas valides en tant qu'enfant React (trouvé: objet avec les clés {XXXXX}). Si vous vouliez rendre une collection d'enfants, utilisez plutôt un tableau.

C'était mon code:

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

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

Solution:

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

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

Le problème se produisait car la charge utile envoyait l'élément en tant qu'objet. Lorsque j'ai supprimé la variable de charge utile et mis la valeur userInput dans la répartition, tout a commencé à fonctionner comme prévu.

bprdev
la source
1

Si vous utilisez Firebase l'un des fichiers de votre projet. Ensuite, placez simplement cette déclaration d'importation Firebase à la fin !!

Je sais que cela semble fou, mais essayez-le !!

KNDheeraj
la source
1

Mon problème était simple lorsque j'ai rencontré l'erreur suivante:

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

était juste que je passais un objet avec des clés spécifiées dans l'erreur en essayant de rendre l'objet directement dans un composant en utilisant {object} en m'attendant à ce qu'il soit une chaîne

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

lors du rendu sur un composant React, j'ai utilisé quelque chose comme ci-dessous

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

mais il aurait dû être

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

Si vous utilisez des composants sans état, suivez ce type de format:

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

Cela a semblé fonctionner pour moi

ppak10
la source
1

Quelque chose comme ça vient de m'arriver ...

J'ai écrit:

{response.isDisplayOptions &&
{element}
}

Le placer à l'intérieur d'un div fixe:

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

Trouvé: objet avec clés

Ce qui signifie que vous passez quelque chose est une valeur-clé. Vous devez donc modifier votre gestionnaire:

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

Vous avez raté les accolades ( {}).

Arul Mani
la source
1
ne peut pas croire que c'était le problème
kushal.8
je me demande aussi. n'a toujours pas compris quel est le problème à cause de cela
Arul Mani
1

Dans mon cas, j'ai ajouté un async à mon composant de fonction enfant et j'ai rencontré cette erreur. N'utilisez pas async avec le composant enfant.

tolga
la source
0

En cas d'utilisation de Firebase, si cela ne fonctionne pas en mettant à la fin des importinstructions, vous pouvez essayer de mettre cela à l'intérieur de la méthode du cycle de vie, c'est-à-dire que vous pouvez le mettre à l'intérieur componentWillMount().

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

Invariant Violation: Objects are not valid as a React childqui m'est arrivé lors de l'utilisation d'un composant qui avait besoin d' renderItemaccessoires, comme:

renderItem={this.renderItem}

et mon erreur a été de faire ma renderItemméthode async.

vmarquet
la source
0

Mon erreur était due à l'écriture de cette façon:

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



au lieu de:

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

Cela signifiait que j'essayais de rendre l'objet au lieu de la valeur qu'il contenait.

edit: c'est pour réagir non natif.

Deke
la source