it-roy-ru.com

Нарушение инварианта: объекты недопустимы как дочерний элемент React

В функции рендеринга моего компонента у меня есть:

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

все отрисовывается нормально, однако при нажатии на элемент <li> я получаю следующую ошибку:

Uncaught Ошибка: Инвариантное Нарушение: Объекты недопустимы как дочерний элемент React (найдено: объект с ключами {dispatchConfig, dispatchMarker, nativeEvent, target, currentTarget, типом, eventPhase, пузыри, cancellable, timeStamp, defaultPrevented, isTrusted , view, detail, screenX, screenY, clientX, clientY, ctrlKey, shiftKey, altKey, metaKey, getModifierState, кнопка, кнопки, relatedTarget, pageX, pageY, isDefaultPrevented, isPropagationStopped, _dispatchListeners, _dispatchIDs}). Если вы намеревались визуализировать коллекцию дочерних элементов, используйте вместо этого массив или оберните объект, используя createFragment (object) из дополнений React. Проверьте метод визуализации Welcome.

Если я изменю на this.onItemClick.bind(this, item) на (e) => onItemClick(e, item) внутри функции карты, все будет работать как положено.

Если бы кто-то мог объяснить, что я делаю неправильно, и объяснить, почему я получаю эту ошибку, было бы здорово

ОБНОВЛЕНИЕ 1:
Функция onItemClick работает следующим образом, и удаление this.setState приводит к исчезновению ошибки.

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

Но я не могу удалить эту строку, так как мне нужно обновить состояние этого компонента

252
almeynman

У меня была эта ошибка, и оказалось, что я непреднамеренно включил объект в мой код JSX, который, как я ожидал, был строковым значением:

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

breadcrumbElement раньше была строкой, но из-за рефакторинга стала объектом. К сожалению, сообщение об ошибке React не помогло мне указать на строку, где существовала проблема. Мне приходилось следить за трассировкой стека до тех пор, пока я не распознал «реквизиты», передаваемые в компонент, а затем не обнаружил код, вызывающий сбой.

Вам нужно будет либо сослаться на свойство объекта, которое является строковым значением, либо преобразовать объект в желаемое строковое представление. Одним из вариантов может быть JSON.stringify, если вы действительно хотите увидеть содержимое объекта.

302
Code Commander

Поэтому я получил эту ошибку при попытке отобразить свойство createdAt, которое является объектом Date. Если вы соедините .toString() в конце, как это, он выполнит преобразование и устранит ошибку. Просто разместите это как возможный ответ на тот случай, если кто-то столкнется с такой же проблемой:

{this.props.task.createdAt.toString()}
79
Brett84c

Я только что получил ту же ошибку, но из-за другой ошибки: я использовал двойные скобки, такие как:

{{count}}

вставить значение count вместо правильного:

{count}

который компилятор предположительно превратил в {{count: count}}, то есть пытается вставить объект как дочерний элемент React.

26
Dogbert

Просто подумал, что я добавлю к этому, поскольку у меня была та же проблема сегодня, оказалось, что это потому, что я возвращал только функцию, когда я обернул ее в тег <div>, он начал работать, как показано ниже

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

Вышеуказанное вызвало ошибку. Я исправил проблему, изменив раздел return() на:

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

... или просто:

return gallerySection
20
user2997982

Моя была связана с ненужной наложением фигурных скобок на переменную, содержащую HTML-элемент внутри оператора return функции render (). Это заставило React рассматривать его как объект, а не как элемент.

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

  return (
    {element}
  )
}

Как только я удалил фигурные скобки из элемента, ошибка исчезла, и элемент был отображен правильно.

9
Liran H

Моя была связана с тем, что забыла о фигурных скобках вокруг реквизита, отправляемых в презентационный компонент:

До:

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

После

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

Для любого, кто использует Firebase с Android, это только ломает Android. Моя эмуляция iOS игнорирует это.

И как отправлено Апурв Банки выше. 

Все, что выше Firebase V5.0.3, для Android, atm - это провал. Fix:

npm i --save [email protected]

Подтверждено много раз здесь https://github.com/firebase/firebase-js-sdk/issues/871

7
RedEarth

Реакция child/children должна быть типом примитива, а не объекта. Используйте пакет Proptypes в разработке, чтобы убедиться, что проверка происходит.

Просто быстрое сравнение кода (JSX), чтобы представить вас с идеей:

  1. Ошибка: при передаче объекта в дочерний объект

    <div>
    {/* item is object with user's name and its other details on it */}
     {items.map((item, index) => {
      return <div key={index}>
    --item object is passed which is error--->>>{item}</div>;
     })}
    </div>
    
  2. Успех: со свойством объекта (которое должно быть примитивным, то есть строковым или целочисленным значением), передаваемым в child.

    <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; (Из ссылки ниже): Убедитесь, что все элементы, которые вы отображаете в JSX, являются примитивами, а не объектами при использовании React. Эта ошибка обычно возникает из-за того, что функции, участвующей в отправке события, был присвоен неожиданный тип объекта (т.е. передается объект, когда вы должны передавать строку), или часть JSX в вашем компоненте не ссылается на примитив (то есть this.props против this.props.name).

Источник - https://www.codingbismuth.com/objects-are-not-valid-as-react-child/

5
Meet Zaveri

Если по какой-то причине вы импортировали FireBase. Затем попробуйте запустить npm i --save [email protected]. Это потому, что firebase break реагирует на нативную, поэтому запуск этого исправит это. 

4
Apoorv Bankey

У меня тоже такая же проблема, но моя ошибка такая глупая. Я пытался получить доступ к объекту напрямую.

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

}
3
Nimmi Verma

Нечто подобное только что случилось со мной ...

Я написал:

{response.isDisplayOptions &&
{element}
}

Поместив его в div исправил это:

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

Вы просто использовали ключи объекта, а не весь объект!

Более подробную информацию можно найти здесь: 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
user8202629

Моя проблема была проста, когда я столкнулся со следующей ошибкой:

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

просто я передавал объект с ключами, указанными в ошибке, при попытке отобразить объект непосредственно в компоненте, используя {объект}, ожидая, что он будет строкой

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

при рендеринге на React Component я использовал что-то вроде ниже

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

но это должно было быть

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

Я хотел бы добавить другое решение в этот список.

Технические характеристики:

  • «реагировать»: «^ 16.2.0»,
  • «Reaction-DOM»: «^ 16.2.0»,
  • «response-redux»: «^ 5.0.6»,
  • "response-scripts": "^ 1.0.17",
  • "redux": "^ 3.7.2"

Я столкнулся с той же ошибкой:

Uncaught Error: объекты недопустимы как дочерние элементы React (найдено: объект С ключами {XXXXX}). Если вы хотели сделать коллекцию детей, вместо этого используйте массив.

Это был мой код:

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

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

Решение:

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

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

Проблема возникла из-за того, что полезная нагрузка отправляла элемент как объект. Когда я удалил переменную полезной нагрузки и поместил значение userInput в диспетчеризацию, все начало работать как положено.

1
bprdev

У меня та же проблема, в моем случае, Я обновляю состояние redux , и новые параметры данных не соответствуют старым параметрам, поэтому, когда я хочу получить доступ к некоторым параметрам через эту ошибку,

Может быть, этот опыт поможет кому-то 

1
MohammadMasoumi

При использовании компонентов без сохранения состояния придерживайтесь следующего формата:

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

Казалось, это работает для меня

1
ppak10

Если в случае, если вы используете Firebase какой-либо из файлов в вашем проекте . Тогда просто поместите этот оператор import firebase в конце !!

Я знаю, это звучит безумно, но попробуй !!

1
KNDheeraj

Я тоже получал эту ошибку "Объекты недопустимы как дочерний элемент React", и для меня причина была вызвана асинхронной функцией в моем JSX. Увидеть ниже.

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

Я узнал, что асинхронный рендеринг не поддерживается в React. Команда React работает над решением, которое задокументировано здесь .

Кругозор

1
Ken A Collins

Моя проблема была очень особенной: в моем файле .env я поместил комментарий в строку с моим api url:

API_URL=https://6ec1259f.ngrok.io #comment

Я получаю ошибку Invariant violation при попытке войти/зарегистрироваться, так как URL-адрес API был неверным.

0
ehacinom

Моя ошибка была из-за того, что я написал это так:

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



вместо:

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

Это означало, что я пытался визуализировать объект вместо значения внутри него.

Правка: это для реагировать не родной.

0
Deke

В моем случае я забыл вернуть элемент html из функции рендеринга, и я возвращал объект. Я только что обернул {items} элементом html - простым div, как показано ниже

<ul>{items}</ul>

0
Shan

Invariant Violation: Objects are not valid as a React child произошел со мной при использовании компонента, который нуждался в реквизите renderItem, например:

renderItem={this.renderItem}

и моя ошибка заключалась в том, чтобы сделать мой метод renderItemasync.

0
vmarquet

Очевидно, что, как уже упоминалось ранее в этой теме, в React JSX props.childrenне может иметь тип Object . Это НЕ первопричина для проблемы в вашем конкретном вопросе.

Если вы внимательно прочитаете текст ошибки, вы увидите, что React выдал ошибку при попытке отобразить объект, который соответствует подписи SyntheticEvent :

Uncaught Error: Invariant Violation: Objects are not valid as a React child (found: object with keys {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}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of Welcome.

Однако возникает вопрос, почему вы пытаетесь отобразить SyntheticEvent, и именно в этом заключается реальный ответ на ваш вопрос. У вас явно нет намерения отображать переменную SyntheticEvent, но вы получили параметры обработчика событий не в порядке.

В вашем методе render вы связываете обработчик события onItemClick с this вашего компонента класса и передаете item в качестве аргумента:

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

В соответствии с документацией для Function.prototype.bind , все аргументы, передаваемые после thisArg, являются предварительно добавленными для любых аргументов, которые впоследствии передаются при последующем вызове целевой функции:

arg1, arg2, ...

Аргументы для добавления к аргументам, предоставляемым связанной функции при вызове целевой функции.

Если мы затем посмотрим на обработчик событий, то увидим, что параметр e указан перед параметром item.

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

Когда вызывается onItemClick(e, item), item, переданный во время вызова bind, будет предшествовать триггеру event, поэтому параметр e будет установлен на сопоставленный и связанный item, а параметр item будет установлен в event.

Когда вызывается setState, для lang будет установлено значение SyntheticEvent, представляющее инициирующее событие onClick, и когда вы попытаетесь отобразить значение в this.state.lang в другом месте, вы получите ошибку Invariant Violation, которую вы видели.

0
Philip Wrage

Firebase 2019

Если вы используете Firebase и видите эту ошибку, стоит проверить, правильно ли вы ее импортируете. Начиная с версии 5.0.4, вы должны импортировать его так:

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

Да, я знаю. Я тоже потерял 45 минут.

0
Lucas Bustamante
  1. Происходит то, что функция onClick, которую вы пытаетесь реализовать, запускается немедленно.

  2. Поскольку наш код не является HTML, это javascript, поэтому он интерпретируется как выполнение функции.

  3. функция onClick принимает функцию в качестве аргумента, а не выполнение функции.

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

это определит функцию onClick для элемента списка, которая будет выполнена после нажатия на нее не сразу после рендеринга нашего компонента.

0
Hassan Raza

В случае использования Firebase, если он не работает, помещая в конце операторы import, вы можете попытаться поместить это в один из методов жизненного цикла, то есть вы можете поместить его в componentWillMount().

componentWillMount() {
    const firebase = require('firebase');
    firebase.initializeApp({
        //Credentials
    });
}
0
Germa Vinsmoke
try{
    throw new Error(<p>An error occured</p>)
}catch(e){
    return (e)
}

Приведенный выше код выдал ошибку, затем я переписал ее так:

try{
    throw(<p>An error occured</p>)
}catch(e){
    return (e)
}

Обратите внимание на удаление новой ошибки () в блоке try ...

Лучший способ написать код, чтобы избежать появления этого сообщения об ошибке Ожидается, что объект будет выброшен no-throw-literal - передать строку в throw new Error () вместо JSX и вернуть JSX в вашем блоке catch что-то вроде этого:

try{
    throw new Error("An error occurred")
}catch(e){
    return (
        <p>{e.message}</p>
    )
}
0
Peter Moses Mohemos

Вы можете отобразить массив непосредственно в тексте. либо вам нужно разбить или перебрать массив и отобразить в FlatList

Например this.props.items = ["A", "B", "C"]

вы должны отобразить как <Text>{JSON.strignify(this.props.items)}</Text>

или же

 <FlatList
    data={this.props.items}
    renderItem={(item)=>{
    <Text>{item}</Text>
    }}
     />
0
Rajesh Nasit

Я просто изложил по-настоящему глупую версию этой ошибки, которой я также могу поделиться здесь для будущих поколений.

У меня был такой JSX, как этот:

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

Мне нужно было закомментировать это, чтобы что-то отладить. Я использовал сочетание клавиш в моей IDE, что привело к следующему:

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

Что, конечно, недействительно - объекты недействительны как реагирующие дети!

0
shabs

Найдено: объект с ключами

Это означает, что вы передаете что-то - это ключ-значение, поэтому вам нужно изменить ваш обработчик.

от

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

К

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

Вы пропустили скобки ({}).

0
Arul Mani