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

时间:2015-10-14 05:43:57

标签: javascript reactjs

在我的组件的渲染功能中,我有:

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   child(找到:带键的对象{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})。如果您要渲染子集合,请使用数组,或使用createFragment(object)包装对象   React附加组件。检查Welcome的呈现方法。

如果我在地图功能中更改为this.onItemClick.bind(this, item)(e) => onItemClick(e, item),一切都会按预期工作。

如果有人可以解释我做错了什么并解释为什么我会收到这个错误,那就太棒了

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

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

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

44 个答案:

答案 0 :(得分:323)

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

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

breadcrumbElement曾经是一个字符串,但由于重构已成为一个Object。不幸的是,React的错误信息并没有很好地指出我存在问题的那一行。我不得不一直跟着我的堆栈跟踪,直到我认识到传递给组件的“道具”,然后我发现了有问题的代码。

您需要引用作为字符串值的对象的属性,或者将Object转换为所需的字符串表示形式。如果您确实想要查看对象的内容,则一个选项可能是JSON.stringify

答案 1 :(得分:84)

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

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

答案 2 :(得分:27)

我得到了同样的错误,但由于一个不同的错误:我使用双括号,如:

{{count}}

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

{count}

编译器可能会变成{{count: count}},即尝试将Object作为React子进行插入。

答案 3 :(得分:24)

以为我会添加到此,因为我今天遇到了同样的问题,结果是因为我只返回了该函数,当我将它包装在<div>标签中时它开始工作,如下所示< / p>

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

以上导致错误。我通过将return()部分更改为:

来解决问题
return (
  <div>
    {gallerySection}
  </div>
);

......或简单地说:

return gallerySection

答案 4 :(得分:12)

我必须不必要地在一个包含render()函数的return语句中的HTML元素的变量周围放置花括号。这使得React将其视为对象而非元素。

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

  return (
    {element}
  )
}

一旦我从元素中删除了大括号,错误消失了,元素被正确呈现。

答案 5 :(得分:8)

我不得不忘记发送到演示组件的道具周围的花括号:

在:

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

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

答案 6 :(得分:7)

反应子(单数)应为primitive数据类型,而不是对象,或者可以是JSX标记(在我们的情况下不是)。在开发过程中使用Proptypes程序包以确保进行验证。

只是一个快速的代码片段(JSX)比较,可以代表您一些想法:

  1. 错误:对象被传递给子对象

    computed: {     
        exampleComputed: function () {
            return this.string;
         }
    }
    
  2. 没有错误:将对象的属性(应该是原始的,即字符串值或整数值)传递给子级。

        data Mono1;
           input Obs Trt y0 y1;
           cards;
        1 0 10.5212 11.3604
        2 0 8.5871 8.5178
        3 0 9.3274 .
        4 0 9.7519 .
        5 0 9.3495 9.4369
        6 1 11.5192 13.1344
        7 1 10.7841 .
        8 1 9.7717 10.8407
        9 1 10.1455 10.7279
        10 1 8.2463 9.5844
           ;
        run;
    
        data parm1; 
         input Obs _IMPUTATION_ SHIFT_C shift_t; 
         cards;
        1 1 -0.56986 -0.90494
        2 2 -0.38681 -0.84523
        3 3 -0.58342 -0.92793
        4 4 -0.48210 -0.99031
        5 5 -0.57188 -1.02095
        6 6 -0.57604 -1.008
        ;run;
    
        proc mi data=Mono1 seed=1423741 nimpute=6 out=outex18;
            class Trt;
            monotone reg;
            mnar adjust( y1 / adjustobs=(Trt='0') parms(shift=SHIFT_C)=parm1)
                adjust( y1 / adjustobs=(Trt='1') parms(shift=shift_t)=parm1);
            var Trt y0 y1;
        run;
    

TLDR; (从下面的链接):确保在使用React时,您在JSX中渲染的所有项目都是基元而不是对象。发生此错误的原因通常是,与分派事件有关的函数已被赋予了意外的对象类型(即,当您应该传递字符串时传递对象),或者组件中的JSX的一部分未引用原语(即this.props与this.props.name)。

来源-https://www.codingbismuth.com/objects-are-not-valid-as-react-child/

答案 7 :(得分:7)

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

并由上方的Apoorv Bankey发布。

对于Firebase V5.0.3而言,对于Android而言,atm都是破产。修复:

npm i --save firebase@5.0.3

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

答案 8 :(得分:4)

我也有同样的问题,但是我的错误太愚蠢了。我试图直接访问对象。

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

}

答案 9 :(得分:4)

这是我的代码:

class App extends Component {
  constructor(props){
    super(props)
    this.state = {
      value: null,
      getDatacall : null
    }
    this.getData = this.getData.bind(this)
  }
  getData() {
  //   if (this.state.getDatacall === false) {
    sleep(4000)
    returnData("what is the time").then(value => this.setState({value, getDatacall:true}))
    // }
  }
  componentDidMount() {
    sleep(4000)

    this.getData()
  }
  render() {
    this.getData()
    sleep(4000)
    console.log(this.state.value)
    return (
      <p> { this.state.value } </p>
    )
  }
}

我遇到了这个错误。我不得不把它改成

 render() {
    this.getData()
    sleep(4000)
    console.log(this.state.value)
    return (
      <p> { JSON.stringify(this.state.value) } </p>
    )
  }

希望这对某人有所帮助!

答案 10 :(得分:4)

如果出于某种原因您导入了Firebase。然后尝试运行npm i --save firebase@5.0.3。这是因为firebase break反应为原生,因此运行此程序将对其进行修复。

答案 11 :(得分:3)

通常会弹出此窗口,因为您没有正确地进行破坏。以下面的代码为例:

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只是期望一个带有键和值的对象。

使用object destructuring,您可以做并且经常看到这样的事情:

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

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

...有效。

机会是,任何绊脚石的人都会不经意间声明其组件的道具参数。

答案 12 :(得分:2)

像这样的事情刚刚发生在我身上...

我写道:

{response.isDisplayOptions &&
{element}
}

将其放置在div内进行修复:

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

答案 13 :(得分:2)

在我的情况下,我忘记了返回render函数的html元素,而我却返回了一个对象。我所做的只是将{items}用html元素包裹-像下面这样的简单div

<ul>{items}</ul>

答案 14 :(得分:2)

我遇到了同样的问题,因为我没有将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>
    );
}

答案 15 :(得分:2)

你只是使用了对象的键,而不是整个对象!

可在此处找到更多详细信息:https://github.com/gildata/RAIO/issues/48

&#13;
&#13;
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;
&#13;
<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>
&#13;
&#13;
&#13;

答案 16 :(得分:1)

我遇到了同样的错误,我对此进行了更改

export default withAlert(Alerts)

对此

export default withAlert()(Alerts)

在较早的版本中,以前的代码可以,但是在较新的版本中,它将引发错误。因此,请使用后面的代码来避免出现错误。

答案 17 :(得分:1)

每当我在FlatList中的renderItem函数上调用异步时,都会遇到此错误。

在调用FlatList中的状态数据之前,我必须创建一个新函数将Firestore集合设置为我的状态。

答案 18 :(得分:1)

如果您正在使用Firebase并看到此错误,则值得检查是否正确导入了它。从5.0.4版开始,您必须像这样导入它:

id

是的,我知道。我也为此损失了45分钟。

答案 19 :(得分:1)

我的情况在使用reduce时很常见,但这里没有分享,所以我发布了。

通常,如果来自服务器响应的数组如下所示:

const array = [{ value: 1}, {value: 2}]

并且您想在此数组中呈现 value 的总和。 JSX 代码看起来像这样

<div>{array.reduce((acc, curr) => acc.value + curr.value)}</div>

当您的数组只有一项时会出现问题,例如:[{value: 1}];

reduce 代码行将立即返回 value 中的元素,它是一个对象并导致错误。

答案 20 :(得分:1)

在我的组件名称中使用了 async,然后我遇到了这个问题,

const Register = async () => {
<块引用>

ERROR 错误:对象作为 React 子对象无效(找到:对象 键 {_U, _V, _W, _X})。如果您打算渲染一组 孩子们,请改用数组。

然后我意识到并删除了它,问题为我解决了,

const Register = () => {

答案 21 :(得分:1)

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

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

这似乎对我有用

答案 22 :(得分:1)

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

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

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

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

在React组件上渲染时,我使用了类似下面的内容

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

但应该如此

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

答案 23 :(得分:1)

就我而言,我有同样的问题, 我更新了 redux 状态,并且新的数据参数与旧参数不匹配,所以当我想通过此错误访问某些参数时,

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

答案 24 :(得分: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})。如果你想渲染一个孩子的集合,   改为使用数组。

这是我的代码:

display:none

解决方案:

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

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

问题出现了,因为有效负载正在将项目作为对象发送。当我删除有效负载变量并将userInput值放入调度时,一切都按预期开始工作。

答案 25 :(得分:1)

如果您使用Firebase项目中的任何文件。 然后在最后放置导入firebase语句!!

我知道这听起来很疯狂但是试试!!

答案 26 :(得分: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)
}

请注意在try块中删除了 new Error() ...

为了避免出现此错误消息,编写代码的一种更好的方法期望没有抛出异常的对象是将字符串传递给抛出新的Error()< / strong>而不是JSX,然后在您的catch块中返回JSX,如下所示:

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

答案 27 :(得分:0)

任何遭受此错误的人。 检查您是否传递对象而不是传递对象以外的其他数据类型。

答案 28 :(得分:0)

我只是通过一个非常愚蠢的错误版本,我也可以在这里分享后代。

我有一些像这样的JSX:

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

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

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

当然,这是无效的 - 对象作为反应孩子无效!

答案 29 :(得分:0)

尝试一下

 {items && items.title ? items.title : 'No item'}

答案 30 :(得分:0)

在使用Firebase的情况下,如果通过将import语句放在末尾而无法正常工作,则可以尝试将其放入生命周期方法之一,即可以将其放入在componentWillMount()内。

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

答案 31 :(得分:0)

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

答案 32 :(得分:0)

Invariant Violation: Objects are not valid as a React child在使用需要renderItem道具的组件时发生在我身上,例如:

renderItem={this.renderItem}

我的错误是使我的renderItem方法async

答案 33 :(得分: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>)
})

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

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

答案 34 :(得分:0)

在我的情况下,这是因为必须在运行时插入动态数组。

我刚刚添加了对象的空检查,它工作正常。

之前:

...
render(
...
    <div> {props.data.roles[0]} </div>
...
);

之后:

...
let items = (props && props.data && props.data.roles)? props.data.roles: [];
render(
...
    <div> {items[i]} </div>
...
);

答案 35 :(得分:0)

对于那些提到Stringify()toString()作为解决方案的人,我会说这对我有用,但是我们必须了解这个问题以及为什么会发生。在我的代码中,这是一个简单的问题。我有2个调用相同功能的按钮,但有1个按钮未正确将参数传递给该函数。

答案 36 :(得分:0)

我在使用三元运算符呈现某些内容时遇到此错误。 我做了什么:

render(){
  const bar = <div>asdfasdf</div>
  return ({this.state.foo ? {bar} : <div>blahblah</div>})
}

结果应该是没有括号的栏,例如:

render(){
  const bar = <div>asdfasdf</div>
  return ({this.state.foo ? bar : <div>blahblah</div>})
}

答案 37 :(得分:0)

只需创建一个有效的JSX元素。就我而言,我为对象分配了一个组件。

const AwesomeButtonComponent = () => <button>AwesomeButton</button>
const next = {
  link: "http://awesomeLink.com",
  text: "Awesome text",
  comp: AwesomeButtonComponent
}

我想在代码的其他地方动态分配该按钮。

return (
  <div>
    {next.comp ? next.comp : <DefaultAwesomeButtonComp/>}
  </div>
)

我通过声明一个通过props comp初始化的JSX comp解决了这个问题。

const AwesomeBtnFromProps = next.comp
return (
  <div>
    {next.comp ? <AwesomeBtnFromProps/> : <DefaultAwesomeButtonComp/>}
  </div>
)

答案 38 :(得分:0)

我也收到了“对象无效作为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团队正在研究here记录的解决方案。

答案 39 :(得分:0)

找到:带有键的对象

这意味着您传递的东西是键值,因此您需要修改处理程序。

来自

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

收件人

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

您错过了花括号({})。

答案 40 :(得分:0)

很显然,正如其他人在此线程中前面提到的那样,在React JSX props.children cannot be of type Object中。 这不是您特定问题中问题的根本原因

如果您仔细阅读错误文本,将会发现React在尝试渲染与SyntheticEvent签名匹配的Object时产生了错误:

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,并且尝试在{{1}中呈现值}在其他地方,您将收到看到的Invariant Violation错误。

答案 41 :(得分:0)

我的问题很特别:在我的.env文件中,我在具有我的api网址的行中添加了注释:

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

由于api网址错误,尝试登录/注册时会出现Invariant violation错误。

答案 42 :(得分: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函数,该函数将在单击它后立即执行,而不是我们的组件呈现出来。

答案 43 :(得分:-5)

感谢a comment by zerkms,我能够注意到我的愚蠢错误:

当我应该onItemClick(e, item)时,我有onItemClick(item, e)