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

211

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

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> появляется следующая ошибка:

Непринятая ошибка: инвариантное нарушение: объекты недействительны как реакция ребенок (найдено: объект с ключами {dispatchConfig, dispatchMarker, nativeEvent, target, currentTarget, type, eventPhase, bubbles, cancelable, 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,
    });
}

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

  • 2
    Так как реализован this.onItemClick ?
  • 0
    @zerkms Спасибо за ответ, я обновил вопрос, и да, похоже, проблема в this.setState (), но почему он выдает эту ошибку? :(
Показать ещё 4 комментария
Теги:

26 ответов

276

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

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

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

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

  • 9
    Итак, если у вас есть объект, как бы вы превратили его в нечто желаемое?
  • 2
    Вам нужно будет либо сослаться на свойство объекта, которое является строковым значением, либо преобразовать объект в желаемое строковое представление. Одним из вариантов может быть JSON.stringify, если вы действительно хотите видеть содержимое объекта.
Показать ещё 3 комментария
81

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

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

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

{{count}}

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

{count}

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

  • 3
    что {{}} предназначено для /
  • 3
    @MuneemHabib - это просто синтаксис ES6. Реакту нужна одна пара {} . Внутренняя пара рассматривается как код ES6. В ES6 {count} совпадает с {count: count} . Поэтому, когда вы набираете {{count}} , это точно так же, как { {count: count} } .
Показать ещё 1 комментарий
19

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

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

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

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

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

return gallerySection
  • 4
    или вы можете просто использовать return gallerySection если вы хотите избежать дополнительного div
  • 4
    Возвращение gallerySection вместо <div>{gallerySection}</div> мне помогло.
8

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

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

  return (
    {element}
  )
}

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

8

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

До:

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

После

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

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

И как опубликовал Apoorv Bankey выше.

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

npm i --save [email protected]

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

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

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

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

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

    <div>
    {/* item is object with user 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. Успех: с объектным свойством (которое должно быть примитивным, то есть строковым или целочисленным значением) передаваться в дочерний объект.

    <div>
     {/* item is object with user 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>
    

TL;DR; (Из приведенной ниже ссылки). Убедитесь, что все элементы, которые вы визуализируете в JSX, являются примитивами, а не объектами при использовании React. Эта ошибка обычно возникает из-за того, что функция, участвующая в диспетчеризации события, получает неожиданный тип объекта (т.е. Передачу объекта, когда вы должны передавать строку), или часть JSX в вашем компоненте не ссылается на примитив (т.е. this.props vs this.props.name).

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

3

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

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

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

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

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

Я написал:

{response.isDisplayOptions &&
{element}
}

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

{response.isDisplayOptions &&
    <div>
        {element}
    </div>
}
1

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

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

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

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

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

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

  • 0
    В моем случае (Django) ListSerializer и CreateSerializer возвращают одинаковые поля, а некоторые из них (это зависит от вашего проекта) являются полями только для чтения, так что выбирайте один раз и всякий раз, когда создаются новые данные, просто обновляйте состояние избыточности
1

Если в случае использования Firebase любого из файлов в вашем проекте. Затем просто поместите этот импортный заголовок в конец!

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

  • 0
    Это работает для эмулятора Android
1

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

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

  • "реагировать": "^ 16.2.0",
  • "реакция": "^ 16.2.0",
  • "реакция-редукция": "^ 5.0.6",
  • "реакции-скрипты": "^ 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 в диспетчеру, все начало работать как ожидалось.

0
  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
try{
    throw new Error(<p>An error occured</p>)
}catch(e){
    return (e)
}

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

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

Обратите внимание на удаление новой Error() в блоке 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

просто понизить firebase до 5.0.3, похоже, исправлено

npm install [email protected] --save
0

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

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

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

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

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

edit: это для реакции не родной.

0

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

renderItem={this.renderItem}

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

0

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

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

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

У меня был JSX:

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

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

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

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

-3

Благодаря комментарию zerkms я смог заметить свою глупую ошибку:

У меня был onItemClick(e, item) когда у меня должен был быть onItemClick(item, e).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню