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

337

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

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, цель, currentTarget, тип, eventPhase, пузырьки, отменяемый, timeStamp, defaultPrevented, isTrusted, просмотр, детализация, 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,
    });
}

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

almeynman
источник
2
Так как this.onItemClickэто реализовано?
zerkms
@zerkms Спасибо за ответ, я обновил вопрос, и да, похоже, проблема в this.setState (), но почему он выдает эту ошибку? :(
Алмейнман
Есть ли синтаксическая ошибка в setState? Лишняя запятая? Может не исправить ошибку, но только что нашел ее.
Бхаргав Поннапалли
@bhargavponnapalli запятая это вопрос предпочтений, мой эслинт заставляет меня это делать, но удаление не помогает, спасибо за ответ
almeynman
Я получил эту ошибку, когда забыл фигурные скобки вокруг переменной, которая стала объектом с состоянием из локальной переменной после добавления его в состояние в рефакторе.
Jamescampbell

Ответы:

398

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

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

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

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

Code Commander
источник
13
Итак, если у вас есть объект, как бы вы превратили его в нечто желаемое?
adinutzyc21
4
Вам нужно будет либо сослаться на свойство объекта, которое является строковым значением, либо преобразовать объект в желаемое строковое представление. Одним из вариантов может быть JSON.stringify, если вы действительно хотите видеть содержимое объекта.
Code Commander
2
Обнаружена та же ошибка, и это объяснение решило мою проблему. 1 UP для этого. :)
Папски
Ааа, у меня была та же проблема с сообщением об ошибке, указывающим на неправильную строку - там говорилось, что ошибка была в this.setState ({items: items}), когда он действительно взрывался дальше, где я пытался отобразить эту переменную, используя { this.state.items}. JSON.stringify исправил это!
RubberDuckRabbit
Для будущих читателей: нет, не конвертировать в строку. Сделайте это вместо этого: const Lcomponent = this.whwhatReturnsObject (); затем в render () {return <Lcomponent />} Это его.
Ник
102

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

{this.props.task.createdAt.toString()}
Brett84c
источник
2
Бинго! У меня была эта проблема, но она была сбита с пути, потому что таблица, которая отображала ее, загружалась (и перезагружалась) очень хорошо. React выкинет objects are not validинвариантное нарушение, только когда я добавлю строку. Оказывается, я преобразовывал объект Date () в строку перед тем, как сохранить ее, поэтому только мои новые строки имели объекты для созданной даты. :( Учитесь на своём своенравном примере людей!
Стив
37

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

{{count}}

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

{count}

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

Dogbert
источник
3
что {{}} предназначено для /
Муним Хабиб
4
@MuneemHabib - это просто синтаксис ES6. Для реакции нужна одна пара {}. Внутренняя пара рассматривается как код ES6. В ES6 так {count}же, как {count: count}. Поэтому, когда вы печатаете {{count}}, это точно так же, как { {count: count} }.
Догберт
1
Была эта ошибка - это была проблема. При назначении моей переменной состоянию в конструкторе, который у меня был this.state = {navMenuItems: {navMenu}};... который в основном превратил мой JSX navMenuв универсальный объект. Изменение, чтобы this.state = {navMenuItems: navMenu};избавиться от непреднамеренного «приведения» Objectи исправить проблему.
Lowcrawler
30

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

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

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

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

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

return gallerySection
user2997982
источник
8
или вы можете просто использовать, return gallerySectionесли хотите избежать лишнихdiv
Vishal
5
Возвращение gallerySectionвместо того, чтобы <div>{gallerySection}</div>помочь мне.
Занон
16

React child (единственное число) должен быть типом примитивного типа данных, а не объектом, или это может быть тег JSX (что не в нашем случае) . Используйте пакет 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 invalid as react child--->>>{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).

Источник - codingbismuth.com

Познакомьтесь с Завери
источник
2
эта ссылка больше не работает, однако я считаю структуру вашего ответа наиболее информативной в моем случае использования. Эта ошибка может быть получена как в веб-среде, так и в собственной среде реагирования, и часто возникает как ошибка жизненного цикла при попытке .map () массива объектов в компоненте с использованием асинхронного жизненного цикла. Я сталкивался с этой темой, когда использую реагировать нативно реагировать-родной-scrollview
Mibbit
Рад, что вы нашли это полезным, и спасибо за пометку вопроса ссылки.
Познакомьтесь с Завери
1
Это помогло мне. Верните свойство, а не объект:return <p>{item.whatever}</p>;
Крис
15

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

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

  return (
    {element}
  )
}

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

Лиран Х
источник
Спасибо! Снять фигурные скобки с элемента тоже работает у меня!
Хуа Чжан
12

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

Перед:

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

После

const TypeAheadInput = ({name, options, onChange, value, error}) => {
steveareeno
источник
1
Моя проблема была очень похожа на вашу, поэтому применение вашего решения помогло мне. +1 и спасибо!
m1gp0z
9

Я тоже получал эту ошибку «Объекты недопустимы как дочерний элемент 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 работает над решением, описанным здесь .

Кен Коллинз
источник
вместо этого вам следует обновить состояние по мере
поступления
вместо этого вам следует обновить состояние по мере
поступления
7

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

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

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

npm i --save firebase@5.0.3

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

Redearth
источник
Если вы пытаетесь найти решение, предложенное KNDheeraj ниже, **** 1 проголосуйте, если вы используете Firebase любой из файлов в вашем проекте. Тогда просто поместите этот оператор importbase в конце !! Я знаю, это звучит безумно, но попробуй !! **************** Я пробовал, и это не решение для iOS, а только для Android на Windows.
RedEarth
6

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

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

Если по какой-то причине вы импортировали FireBase. Тогда попробуйте запустить npm i --save firebase@5.0.3. Это потому, что firebase break реагирует на «родной», поэтому запуск этого исправит это.

Апурв Банки
источник
3

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

<ul>{items}</ul>

Shan
источник
3

У меня была та же проблема, потому что я не вставил propsфигурные скобки.

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

Так что, если ваш код похож на приведенный выше, вы получите эту ошибку. Чтобы решить эту проблему просто поставьте фигурные скобки по всему props.

export default function Hero({ children, hero }) {
    return (
        <header className={hero}>
            {children}
        </header>
    );
}
Суреш Мангс
источник
@Dharman Я думаю, что это было хорошо понято еще до этого небольшого отступа
Суреш
Я не сказал, что это не так. Я думаю, что ваш ответ выглядит лучше с отступом. Если вы не согласны, пожалуйста, не стесняйтесь откатить назад.
Дхарман
3

Я получил ту же ошибку, я изменил это

export default withAlert(Alerts)

к этому

export default withAlert()(Alerts),

В более старых версиях прежний код был в порядке, но в более поздних версиях он выдает ошибку. Так что используйте более поздний код, чтобы избежать ошибки.

Шубхам Патил
источник
3

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

Код с ошибкой

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

Правильный код

render() {
    var rows = this.props.products.map(product => <tr key={product.id}><td>{product.name}</td><td>{product.price}</td></tr>
    );
    return rows;
}
Намик Гаджиев
источник
2

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

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

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

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

Мохаммад Масуми
источник
В моем случае (Джанго) ListSerializer и CreateSerializer возвращают то же поле , и некоторые из них (это до вашего проекта) только для чтения только полей, поэтому выборки раз и всякий раз , когда создавать новые данные просто обновить состояние Redux
Мохаммад Масого
2

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

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

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

Лукас Бустаманте
источник
Спасибо. Это решило мою проблему с firebase (5.9.2) :)
Mate
2

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

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

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

Мы объявляем это с помощью = text =>параметра. Но на самом деле, React ожидает, что это будет всеобъемлющий propsобъект.

Таким образом, мы действительно должны делать что-то вроде этого:

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

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

Заметили разницу? Параметр propsздесь может быть назван как угодно ( propsэто просто соглашение, соответствующее номенклатуре), React просто ожидает объект с ключами и значениями.

С разрушением объекта вы можете сделать, и часто будете видеть, что-то вроде этого:

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

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

... который работает.

Скорее всего, любой, кто наткнулся на это, просто случайно объявил реквизит реквизита своего компонента без разрушения.

corysimmons
источник
1

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

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

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

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

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

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

shabs
источник
1

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

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

  • «реагировать»: «^ 16.2.0»,
  • «Реакция-Дом»: «^ 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 в диспетчеризацию, все начало работать как положено.

bprdev
источник
1

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

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

KNDheeraj
источник
1

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

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;
}
kaushalop
источник
1

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

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

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

ppak10
источник
1

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

Я написал:

{response.isDisplayOptions &&
{element}
}

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

{response.isDisplayOptions &&
    <div>
        {element}
    </div>
}
Оранит Дар
источник
1

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

Что означает, что вы передаете что-то является ключевым значением. Так что вам нужно изменить ваш обработчик:

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

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

Арул Мани
источник
1
не могу поверить, что это была проблема
kushal.8
я тоже удивляюсь до сих пор не понимаю, что это за причина
Арул Мани
1

В моем случае я добавил асинхронный компонент к своему дочернему компоненту функции и столкнулся с этой ошибкой. Не используйте async с дочерним компонентом.

Толга
источник
0

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

componentWillMount() {
    const firebase = require('firebase');
    firebase.initializeApp({
        //Credentials
    });
}
Герма Винсмоук
источник
0

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

renderItem={this.renderItem}

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

vmarquet
источник
0

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

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

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

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

Deke
источник