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


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.


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

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.


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

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


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.


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}) => {

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 .


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


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

}

4

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


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>


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

@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.


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

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>


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


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.


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.


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!


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.


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 !!


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

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


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

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 ( {}).


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.


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

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.


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.