不变违规:对象作为React子对象无效


337

在组件的render函数中,我有:

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>元素时,出现以下错误:

未捕获的错误:始终违反:对象作为React子对象无效(找到:带有键{dispatchConfig,dispatchMarker,nativeEvent,target,currentTarget,类型,eventPhase,气泡,cancellable,timestamp,defaultPrevented,isTrusted,视图,详细信息,screenX的对象,screenY,clientX,clientY,ctrlKey,shiftKey,altKey,metaKey,getModifierState,按钮,按钮,relatedTarget,pageX,pageY,isDefaultPrevented,isPropagationStopped,_dispatchListeners,_dispatchIDs})。如果您打算渲染孩子的集合,请使用数组代替,或使用React附加组件中的createFragment(object)包装对象。检查的渲染方法Welcome

如果我改变this.onItemClick.bind(this, item)(e) => onItemClick(e, item)地图功能一切正常的内部预期。

如果有人可以解释我做错了什么并解释为什么会出现此错误,那将是很好的

更新1:
onItemClick函数如下,删除this.setState导致错误消失。

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

但是我无法删除此行,因为我需要更新此组件的状态


2
那么如何this.onItemClick实现呢?
zerkms,2015年

@zerkms感谢您的答复,我更新了问题,是的,似乎问题出在this.setState()中,但是为什么它会引发此错误?:(
almeynman

setState中是否存在语法错误?多余的逗号?可能无法修复该错误,但只是找到了它。
Bhargav Ponnapalli 2015年

@bhargavponnapalli逗号是一个优先事项,我的陪同人员强迫我这样做,但是删除它并没有帮助,谢谢您的回复
almeynman 2015年

当我在将变量添加到重构中的状态后,从局部变量变成了有状态对象的变量周围遗忘了花括号时,出现了此错误。
jamescampbell '18 -10-22

Answers:


398

我遇到了这个错误,结果是我无意中在我希望成为字符串值的JSX代码中包含一个对象:

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

breadcrumbElement过去是一个字符串,但由于重构而成为对象。不幸的是,React的错误消息不能很好地指出问题所在。我必须一直跟踪堆栈跟踪,直到我意识到“ props”已传递到组件中,然后才发现有问题的代码。

您需要引用对象的属性(它是字符串值),或者将Object转换为所需的字符串表示形式。一种选择是,JSON.stringify如果您实际上想查看对象的内容。


13
因此,如果您确实有一个对象,将如何将其转换为所需的对象?
adinutzyc21 2016年

4
您需要引用对象的属性(它是字符串值),或者将Object转换为所需的字符串表示形式。如果您实际上想查看Object的内容,则一个选项可能是JSON.stringify。
代码指挥官

2
遇到相同的错误,此说明解决了我的问题。1 UP为此。:)
papski '18

啊,我遇到了同样的错误消息,指向错误的行-它说错误出在this.setState({items:items})上,而实际上它在我试图使用{ this.state.items}。JSON.stringify修复了它!
RubberDuckRabbit

对于将来的读者:不,请不要转换为字符串。改为执行以下操作:const Lcomponent = this.whateverReturnsObject(); 然后在render(){return <Lcomponent />}中。
尼克,

102

因此,当我尝试显示createdAt日期对象的属性时出现了此错误。如果您.toString()像这样最后连接,它将进行转换并消除错误。只是将其作为可能的答案发布,以防其他人遇到相同的问题:

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

2
答对了!我遇到了这个问题,但是由于显示该表的表可以加载(和重新加载)就很好了,因此被淘汰了。objects are not valid当我添加一行时,React只会抛出不变的违规。原来,我在将Date()对象转换为字符串之前将其持久化,因此只有新行具有用于创建日期的对象。:(向我任性的榜样人学习!
Steve

37

我只是遇到了相同的错误,但是由于错误有所不同:我使用了像这样的双括号:

{{count}}

插入值count而不是正确的值:

{count}

编译器大概变成了它{{count: count}},即试图插入一个对象作为React子对象。


3
{{}}的意思是/
Muneem Habib

4
@MuneemHabib只是ES6语法。React需要一对{}。内部对被视为ES6代码。在ES6中,{count}与相同{count: count}。因此,当您键入时{{count}},它与完全相同{ {count: count} }
Dogbert

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

8
或者,return gallerySection如果您想避免额外使用,则可以简单地使用div
Vishal

5
返回gallerySection而不是<div>{gallerySection}</div>帮助了我。
Zanon

16

React child(singular)应该是原始数据类型而不是object 类型,也可以是JSX tag(在我们的例子中不是)。在开发中使用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. 没有错误:将对象的属性(应该是原始的,即字符串值或整数值)传递给子级。

    <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;(来自下面的源代码):确保在使用React时,您在JSX中渲染的所有项目都是基本类型,而不是对象。通常会发生此错误,因为与分派事件有关的函数已被赋予了意外的对象类型(即,当您应该传递字符串时传递对象),或者组件中的JSX的一部分未引用基元(即this.props与this.props.name)。

资料来源-codingbismuth.com


2
该链接不再起作用,但是我发现您的答案的结构在我的用例中是最有用的。该错误在Web环境和本机环境中均会产生,并且在尝试使用异步生命周期尝试对组件内的对象数组进行.map()时,通常会作为生命周期错误发生。我在使用react native react-native-scrollview时遇到了这个线程
mibbit

很高兴您发现它很有用,并感谢您举报链接问题。
与Zaveri

1
这对我有帮助。返回一个属性而不是一个对象:return <p>{item.whatever}</p>;
克里斯

15

我不得不将不必要的花括号放在在render()函数的return语句内包含HTML元素的变量周围。这使得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}) => {

1
我的问题与您的问题最相似,因此应用您的解决方案对我有帮助。+1,谢谢!
m1gp0z

9

我也收到了“对象作为React child无效”错误,对我来说,原因是由于在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团队正在研究此处记录的解决方案。


相反,您应该做的是在输入数据时更新状态,然后使用状态值呈现组件
mrwagaba

相反,您应该做的是在输入数据时更新状态,然后使用状态值呈现组件
mrwagaba

7

对于将Firebase与Android结合使用的任何人,这只会破坏Android。我的iOS仿真忽略了它。

正如上面的Apoorv Bankey发布的那样。

适用于Android的Firebase V5.0.3以上版本的atm都很糟糕。固定:

npm i --save firebase@5.0.3

在这里多次确认 https://github.com/firebase/firebase-js-sdk/issues/871


对于尝试以下KNDheeraj提出的解决方案的任何人,**** 1投反对票如果万一您使用Firebase,则您项目中的任何文件。然后只需将导入的Firebase语句放在末尾即可!!我知道这听起来很疯狂,但请尝试!****************我确实尝试过,但这不是iOS的解决方案,而是Windows上的Android。
RedEthth '18

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

在我的情况下,我忘了从render函数返回一个html元素,而我正在返回一个对象。我所做的只是将{items}与html元素包装在一起-如下所示的简单div

<ul>{items}</ul>


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我认为即使在缩进之前,这也已广为人知
Suresh Mangs

我没有说不是。我认为通过缩进,您的答案看起来更好。如果您不同意,请随时回滚。
Dharman

@Dharman不,太酷了。
Suresh Mangs

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

在我的情况下,我遇到了同样的问题,我更新了redux状态,而新的数据参数与旧参数不匹配,所以当我想通过此错误访问某些参数时,

也许这种经验可以帮助某人


在我的情况下,(Django)ListSerializer和CreateSerializer返回相同的字段,而其中的一些(取决于您的项目)只是只读字段,因此只要一次创建新数据就只要更新redux状态即可获取数据
Mohammad Masoumi

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" />
)

...有效

碰到这个问题的任何人都有可能在不破坏结构的情况下意外地声明了其组件的道具参数。


1

我只是对这个错误做了一个非常愚蠢的版本,我也可以在此分享一下,以供后代参考。

我有一些像这样的JSX:

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

我需要对此进行注释以调试某些内容。我在IDE中使用了键盘快捷键,结果是:

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

当然,这是无效的-对象不是有效的反应子对象!


1

我想向此列表添加另一种解决方案。

眼镜:

  • “ react”:“ ^ 16.2.0”,
  • “ react-dom”:“ ^ 16.2.0”,
  • “ react-redux”:“ ^ 5.0.6”,
  • “ react-scripts”:“ ^ 1.0.17”,
  • “ redux”:“ ^ 3.7.2”

我遇到了同样的错误:

未捕获的错误:对象作为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

如果万一您使用Firebase,则项目中的任何文件。然后只需将导入的Firebase语句放在末尾即可!!

我知道这听起来很疯狂,但请尝试!


1

当我遇到以下错误时,我的问题很简单:

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

只是我正在传递带有错误中指定的键的对象,同时尝试使用{object}直接在组件中呈现该对象,并期望它是一个字符串

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

在React Component上渲染时,我使用了以下内容

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

但是应该是

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

1

如果使用无状态组件,请遵循以下格式:

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

这似乎对我有用


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

我也想知道。仍然没有弄清楚是什么原因造成的
Arul Mani

1

就我而言,我向子功能组件添加了异步,并遇到了此错误。不要对子组件使用异步。


0

在使用Firebase的情况下,如果不能通过在import语句末尾放置Firebase来工作,则可以尝试将其放入生命周期方法之一,也就是可以将其放入内部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


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

这意味着我试图渲染对象而不是其中的值。

编辑:这是为了反应不是本地的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.