Niezmienne naruszenie: Przedmioty nie są ważne jako dziecko React

337

W funkcji renderowania mojego komponentu mam:

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

wszystko renderuje się dobrze, jednak po kliknięciu <li>elementu pojawia się następujący błąd:

Nieprzechwycony błąd: Niezmienne naruszenie: Obiekty nie są poprawne jako dziecko React (znaleziono: obiekt z kluczami {dispatchConfig, dispatchMarker, nativeEvent, target, currentTarget, typ, eventPhase, bąbelki, można anulować, timeStamp, defaultPrevented, isTrusted, widok, szczegół, screenX , screenY, clientX, clientY, ctrlKey, shiftKey, altKey, metaKey, getModifierState, przycisk, przyciski, relatedTarget, pageX, pageY, isDefaultPrevented, isPropagationStopped, _dispatchListeners, _dispatchIDs}). Jeśli chcesz wyrenderować kolekcję dzieci, użyj zamiast tego tablicy lub zawiń obiekt za pomocą createFragment (obiektu) z dodatków React. Sprawdź metodę renderowania dla Welcome.

Jeśli zmienię się this.onItemClick.bind(this, item)do (e) => onItemClick(e, item)wewnątrz funkcji map wszystko działa zgodnie z oczekiwaniami.

Gdyby ktoś mógł wyjaśnić, co robię źle i wyjaśnić, dlaczego dostaję ten błąd, byłoby świetnie

AKTUALIZACJA 1:
Funkcja onItemClick jest następująca, a usunięcie this.setState powoduje zniknięcie błędu.

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

Ale nie mogę usunąć tej linii, ponieważ muszę zaktualizować stan tego komponentu

almeynman
źródło
2
Jak więc this.onItemClickjest wdrażany?
zerkms
@zerkms Dziękuję za odpowiedź, zaktualizowałem pytanie i tak, wygląda na to, że problem występuje w this.setState (), ale dlaczego zgłasza ten błąd? :(
almeynman
Czy w setState występuje błąd składniowy? Dodatkowy przecinek? Może nie naprawić błędu, ale właśnie go znalazłem.
Bhargav Ponnapalli
@ bhargavponnapalli przecinek jest kwestią preferencji, moja eslint zmusza mnie do tego, ale usunięcie go nie pomaga, dziękuję za odpowiedź
almeynman
Wystąpił ten błąd, gdy zapomniałem nawiasów klamrowych wokół zmiennej, która stała się stanowym obiektem ze zmiennej lokalnej po dodaniu jej do stanu w refaktorze.
jamescampbell

Odpowiedzi:

398

Wystąpił ten błąd i okazało się, że nieumyślnie włączyłem Obiekt do mojego kodu JSX, który powinien być wartością ciągu:

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

breadcrumbElementkiedyś był łańcuchem, ale z powodu refaktora stał się Obiektem. Niestety komunikat o błędzie React nie wykonał dobrej roboty, wskazując mi linię, w której występował problem. Musiałem śledzić ślad stosu aż do momentu, gdy rozpoznałem „rekwizyty” przekazywane do komponentu, a potem znalazłem kod, który go narusza.

Musisz odwołać się do właściwości obiektu, która jest wartością ciągu lub przekonwertować obiekt na pożądaną reprezentację ciągu. Jedną z opcji może być, JSON.stringifyjeśli naprawdę chcesz zobaczyć zawartość obiektu.

Code Commander
źródło
13
A więc, jeśli masz jakiś przedmiot, jak mógłbyś go przekształcić w coś pożądanego?
adinutzyc21
4
Musisz odwołać się do właściwości obiektu, która jest wartością ciągu lub przekonwertować obiekt na pożądaną reprezentację ciągu. Jedną z opcji może być JSON.stringify, jeśli faktycznie chcesz zobaczyć zawartość obiektu.
Code Commander
2
Wystąpił ten sam błąd, a to wyjaśnienie rozwiązało mój problem. 1 UP za to. :)
papski
Achh, miałem ten sam problem z komunikatem o błędzie wskazującym niewłaściwą linię - informował, że błąd wystąpił w this.setState ({items: items}), kiedy tak naprawdę wysadził się w dół, gdzie próbowałem wyświetlić tę zmienną za pomocą { this.state.items}. JSON.stringify naprawił to!
RubberDuckRabbit
Dla przyszłych czytelników: Nie, nie konwertuj na ciąg. Zrób to zamiast tego: const Lcomponent = this.whthingReturnsObject (); następnie w render () {return <Lcomponent />} To jest to.
Nick
102

Wystąpił więc ten błąd podczas próby wyświetlenia createdAtwłaściwości, która jest obiektem Date. Jeśli połączysz .toString()w taki sposób, spowoduje to konwersję i wyeliminuje błąd. Po prostu opublikuj to jako możliwą odpowiedź na wypadek, gdyby ktoś napotkał ten sam problem:

{this.props.task.createdAt.toString()}
Brett84c
źródło
2
Bingo! Miałem ten problem, ale zostałem wyrzucony z toru, ponieważ tabela, która go wyświetlała, ładowałaby się (i ładowała) ładnie. React rzuciłby objects are not validniezmienne naruszenie tylko wtedy, gdy dodałem wiersz. Okazuje się, że przekształcałem obiekt Date () w ciąg przed utrwaleniem go, więc tylko moje nowe wiersze zawierały obiekty dla utworzonej daty. :( Ucz się od moich krnąbrnych przykładowych ludzi!
Steve
37

Właśnie dostałem ten sam błąd, ale z powodu innego błędu: użyłem podwójnych nawiasów klamrowych, takich jak:

{{count}}

wstawić wartość countzamiast poprawnej:

{count}

w który prawdopodobnie kompilator się zmienił {{count: count}}, tj. próbuje wstawić obiekt jako dziecko React.

Dogbert
źródło
3
co {{}} są przeznaczone dla /
Muneem Habib
4
@MuneemHabib to tylko składnia ES6. React potrzebuje jednej pary {}. Para wewnętrzna traktowana jest jak kod ES6. W ES6 {count}jest taki sam jak {count: count}. Więc kiedy piszesz {{count}}, jest dokładnie tak samo jak { {count: count} }.
Dogbert
1
Miałem ten błąd - to był problem. Przypisując moją zmienną do stanu w konstruktorze, miałem this.state = {navMenuItems: {navMenu}};... co w zasadzie zmieniło mój JSX navMenuw obiekt ogólny. Zmiana this.state = {navMenuItems: navMenu};polegająca na pozbyciu się niezamierzonego „obsady” Objecti naprawieniu problemu.
lowcrawler
30

Pomyślałem, że dodałbym do tego, ponieważ miałem dzisiaj ten sam problem, okazuje się, że to dlatego, że zwróciłem tylko funkcję, kiedy owinąłem ją w <div>tag, zaczął działać, jak poniżej

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

Powyższe spowodowało błąd. Rozwiązałem problem, zmieniając return()sekcję na:

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

...lub po prostu:

return gallerySection
użytkownik2997982
źródło
8
lub możesz po prostu użyć, return gallerySectionjeśli chcesz uniknąć dodatkowegodiv
Vishal
5
Powrót gallerySectionzamiast <div>{gallerySection}</div>mi pomógł.
Zanon,
16

Dziecko podrzędne React (liczba pojedyncza) powinno być typem prymitywnego typu danych, a nie obiektem, lub może to być znacznik JSX (co nie jest w naszym przypadku) . Użyj pakietu Proptypes w fazie projektowania, aby mieć pewność, że nastąpi weryfikacja.

Wystarczy porównanie krótkiego fragmentu kodu (JSX), aby przedstawić Ci pomysł:

  1. Błąd: z obiektem przekazywanym do dziecka

    <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. Bez błędu: z właściwością obiektu ( która powinna być prymitywna, tj. Wartością ciągu lub wartością całkowitą ) przekazywaną do potomka.

    <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; (Ze źródła poniżej): Upewnij się, że wszystkie elementy renderowane w JSX są prymitywami, a nie obiektami podczas używania React. Ten błąd zwykle występuje, ponieważ funkcja zaangażowana w wywołanie zdarzenia otrzymała nieoczekiwany typ obiektu (tj. Przekazanie obiektu, gdy należy przekazać ciąg) lub część JSX w komponencie nie odwołuje się do operacji podstawowej (tj. This.props vs this.props.name).

Źródło - codingbismuth.com

Poznaj Zaveri
źródło
2
ten link już nie działa, jednak uważam, że struktura twojej odpowiedzi jest najbardziej pouczająca w moim przypadku użycia. Ten błąd można wygenerować zarówno w sieci, jak i w środowisku macierzystym, i często występuje jako błąd cyklu życia podczas próby .map () tablicy obiektów w składniku za pomocą cyklu życia asynchronicznego. Natknąłem się na ten wątek podczas korzystania z polecenia native-respond-native-scroll -view
mibbit
Cieszę się, że okażą się przydatne i dziękuję za zgłoszenie problemu z linkiem.
Spotkaj się Zaveri
1
To mi pomogło. Zwróć właściwość zamiast obiektu:return <p>{item.whatever}</p>;
Chris
15

Moje dotyczyło niepotrzebnego umieszczania nawiasów klamrowych wokół zmiennej zawierającej element HTML wewnątrz instrukcji return funkcji render (). To sprawiło, że React potraktował go raczej jako przedmiot niż element.

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

  return (
    {element}
  )
}

Po usunięciu nawiasów klamrowych z elementu błąd zniknął, a element został zrenderowany poprawnie.

Liran H.
źródło
Dzięki! Usuwanie nawiasów klamrowych z elementu też działa dla mnie!
Hua Zhang,
12

Miałem do czynienia z zapominaniem o nawiasach klamrowych wokół rekwizytów wysyłanych do elementu prezentacyjnego:

Przed:

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

Po

const TypeAheadInput = ({name, options, onChange, value, error}) => {
steveareeno
źródło
1
Mój problem był najbardziej podobny do twojego, więc zastosowanie twojego rozwiązania pomogło mi. +1 i dziękuję!
m1gp0z
9

Ja również otrzymywałem błąd „Obiekty nie są prawidłowe jako dziecko React” i dla mnie przyczyną było wywołanie funkcji asynchronicznej w moim JSX. Patrz poniżej.

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

Nauczyłem się, że renderowanie asynchroniczne nie jest obsługiwane w React. Zespół React pracuje nad rozwiązaniem opisanym tutaj .

Ken A Collins
źródło
zamiast tego należy zaktualizować stan w miarę
wchodzenia
zamiast tego należy zaktualizować stan w miarę
wchodzenia
7

Dla każdego, kto używa Firebase z Androidem, to tylko zepsuje Androida. Moja emulacja iOS ignoruje to.

I jak napisał Apoorv Bankey powyżej.

Wszystko powyżej Firebase V5.0.3, na Androida, bankomat jest przełomem. Naprawić:

npm i --save firebase@5.0.3

Potwierdzony wiele razy tutaj https://github.com/firebase/firebase-js-sdk/issues/871

Czerwona ziemia
źródło
Dla każdego, kto spróbuje rozwiązania zaproponowanego przez KNDheeraj poniżej, **** 1 głos w dół Jeśli w przypadku korzystania z Firebase którykolwiek z plików w projekcie. Następnie umieść tę instrukcję importu firebase na końcu !! Wiem, że to brzmi szalenie, ale spróbuj !! **************** Próbowałem i nie jest to rozwiązanie na iOS, ale na Androida tylko na Windows.
RedEarth
6

Mam również ten sam problem, ale mój błąd jest tak głupi. Próbowałem uzyskać dostęp do obiektu bezpośrednio.

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
źródło
4

Jeśli z jakiegoś powodu zaimportowałeś firebase. Następnie spróbuj uruchomić npm i --save [email protected]. Wynika to z tego, że przerwanie firebase-native reaguje, więc uruchomienie go naprawi.

Apoorv Bankey
źródło
3

W moim przypadku zapomniałem zwrócić element HTML z funkcji renderowania i zwracałem obiekt. To, co zrobiłem, to właśnie otoczyłem {items} elementem html - prostym divem jak poniżej

<ul>{items}</ul>

Shan
źródło
3

Miałem ten sam problem, ponieważ nie włożyłem propsnawiasów klamrowych.

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

Więc jeśli twój kod jest podobny do powyższego, otrzymasz ten błąd. Aby rozwiązać ten problem, po prostu załóż nawiasy klamrowe wokół props.

export default function Hero({ children, hero }) {
    return (
        <header className={hero}>
            {children}
        </header>
    );
}
Suresh Mangs
źródło
@Dharman Myślę, że było to dobrze zrozumiane nawet przed tym małym wcięciem
Suresh Mangs
Nie powiedziałem, że tak nie jest. Myślę, że twoja odpowiedź wygląda lepiej z wcięciem. Jeśli się nie zgadzasz, możesz je wycofać.
Dharman
3

Mam ten sam błąd, zmieniłem to

export default withAlert(Alerts)

do tego

export default withAlert()(Alerts).

W starszych wersjach poprzedni kod działał poprawnie, ale w późniejszych wersjach generuje błąd. Więc użyj późniejszego kodu, aby uniknąć błędu.

Shubham Patil
źródło
3

W moim przypadku wystąpił błąd, ponieważ zwróciłem tablicę elementów w nawiasach klamrowych, zamiast zwracać samą tablicę.

Kod z błędem

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

Poprawny kod

render() {
    var rows = this.props.products.map(product => <tr key={product.id}><td>{product.name}</td><td>{product.price}</td></tr>
    );
    return rows;
}
Namik Hadżijew
źródło
2

Po prostu używałeś kluczy obiektu zamiast całego obiektu!

Więcej informacji można znaleźć tutaj: 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
źródło
2

Mam ten sam problem, w moim przypadku aktualizuję redux stan , a nowe parametry danych nie pasują do starych parametrów, więc kiedy chcę uzyskać dostęp do niektórych parametrów przez ten błąd,

Może to doświadczenie komuś pomoże

Mohammad Masoumi
źródło
W moim przypadku (Django) ListSerializer i CreateSerializer zwracają te same pola, a niektóre z nich (to zależy od twojego projektu) są tylko polami tylko do odczytu, więc pobierz Raz i zawsze, gdy utworzysz nowe dane, po prostu zaktualizuj stan redux
Mohammad Masoumi
2

Jeśli używasz Firebase i widzisz ten błąd, warto sprawdzić, czy go poprawnie importujesz. Od wersji 5.0.4 musisz ją zaimportować w następujący sposób:

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

Tak, wiem. Też straciłem 45 minut.

Lucas Bustamante
źródło
Dziękuję Ci. To rozwiązało mój problem z firebase (5.9.2) :)
Mate
2

Zazwyczaj pojawia się, ponieważ nie niszczysz poprawnie. Weźmy na przykład ten kod:

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

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

Deklarujemy to z = text =>param. Ale tak naprawdę React spodziewa się, że będzie to wszechogarniająceprops obiekt.

Więc naprawdę powinniśmy robić coś takiego:

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

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

Zauważ różnicę? propsParam tutaj mógłby być nazwany coś (props to tylko konwencja, który pasuje do nomenklatury), reagują właśnie spodziewa obiekt z kluczami i odstępach.

Z destrukcją obiektów możesz zrobić i często zobaczysz coś takiego:

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

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

... który działa.

Jest szansa, że ​​każdy, kto się na nią natknie, przypadkowo ogłosił, że rekwizyty swojego komponentu są param bez zniszczenia.

corysimmony
źródło
1

Właśnie przedstawiłem sobie naprawdę głupią wersję tego błędu, którą równie dobrze mogę udostępnić tutaj dla potomności.

Miałem trochę takich JSX:

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

Musiałem to skomentować, aby coś debugować. Użyłem skrótu klawiaturowego w moim IDE, co spowodowało:

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

Co oczywiście jest nieprawidłowe - obiekty nie są ważne, ponieważ reagują na nie dzieci!

shabs
źródło
1

Chciałbym dodać inne rozwiązanie do tej listy.

Okular:

  • „reagować”: „^ 16.2.0”,
  • „reag-dom”: „^ 16.2.0”,
  • „React-redux”: „^ 5.0.6”,
  • „reaguj-skrypty”: „^ 1.0.17”,
  • „redux”: „^ 3.7.2”

Napotkałem ten sam błąd:

Nieprzechwycony błąd: Obiekty nie są poprawne jako dziecko React (znaleziono: obiekt z kluczami {XXXXX}). Jeśli chciałeś renderować zbiór dzieci, użyj zamiast tego tablicy.

To był mój kod:

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

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

Rozwiązanie:

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

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

Problem występował, ponieważ ładunek wysyłał element jako obiekt. Kiedy usunąłem zmienną ładunku i wstawiłem wartość userInput do wysyłki, wszystko zaczęło działać zgodnie z oczekiwaniami.

bprdev
źródło
1

Jeśli w przypadku korzystania z Firebase którykolwiek z plików w projekcie. Następnie umieść tę instrukcję importu firebase na końcu !!

Wiem, że to brzmi szalenie, ale spróbuj !!

KNDheeraj
źródło
1

Mój problem był prosty, gdy napotkałem następujący błąd:

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

po prostu przekazałem obiekt z kluczami określonymi w błędzie podczas próby renderowania obiektu bezpośrednio w komponencie przy użyciu {object} oczekując, że będzie to ciąg znaków

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

podczas renderowania na React Component użyłem czegoś takiego jak poniżej

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

ale powinno być

render() {
    return this.props.object.key1;
}
kaushalop
źródło
1

Jeśli korzystasz ze składników bezstanowych, zastosuj ten format:

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

Wydawało mi się, że to działa

ppak10
źródło
1

Coś takiego właśnie mi się przytrafiło ...

Napisałem:

{response.isDisplayOptions &&
{element}
}

Umieszczenie go w div naprawiło:

{response.isDisplayOptions &&
    <div>
        {element}
    </div>
}
Oranit Dar
źródło
1

Znaleziono: obiekt z kluczami

Co oznacza, że ​​przekazanie czegoś jest kluczową wartością. Musisz więc zmodyfikować program obsługi:

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

Brakowało ci nawiasów klamrowych ( {}).

Arul Mani
źródło
1
nie mogę uwierzyć, że to był problem
kushal.8
też się zastanawiam. wciąż nie wiem, co to jest przyczyną
Arul Mani
1

W moim przypadku dodałem asynchronię do komponentu funkcji potomnej i napotkałem ten błąd. Nie używaj asynchronizacji ze składnikiem potomnym.

Tolga
źródło
0

W przypadku korzystania z Firebase, jeśli to nie działa, umieszczając na końcu importinstrukcji, możesz spróbować umieścić to w jednej z metod cyklu życia, to znaczy, możesz umieścić to w środku componentWillMount().

componentWillMount() {
    const firebase = require('firebase');
    firebase.initializeApp({
        //Credentials
    });
}
Germa Vinsmoke
źródło
0

Invariant Violation: Objects are not valid as a React childprzydarzyło mi się, gdy korzystałem ze składnika wymagającego renderItemrekwizytów, takiego jak:

renderItem={this.renderItem}

a moim błędem było stworzenie mojej renderItemmetody async.

vmarquet
źródło
0

Mój błąd polegał na tym, że napisałem to w ten sposób:

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



zamiast:

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

Oznaczało to, że próbowałem renderować obiekt zamiast wartości w nim zawartej.

edycja: służy do reagowania, a nie rodzimego.

Deke
źródło