不变量冲突:对象作为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 Error: Invariant Violation: object是无效的child (find: object with key {dispatchConfig, dispatchMarker,nativeEvent, target, currentttarget, type, eventPhase, bubbles,取消,timeStamp, defaultprevent, isTrusted, view, detail,screenX, screenY, clientX, clientY, ctrlKey, shiftKey, altKey,metaKey, getModifierState, button, buttons, relatedTarget, pageX,pageY, isdefaultprevent, isPropagationStopped, _dispatchListeners,_dispatchIDs})。如果你打算呈现一个子集合,使用数组代替或使用createFragment(object)包装对象React插件。检查Welcome的渲染方法

如果我在映射函数内将this.onItemClick.bind(this, item)更改为(e) => onItemClick(e, item),一切都按预期工作。

如果有人能解释我做错了什么,解释为什么我得到这个错误,将是伟大的

更新1:


onItemClick函数如下所示,并将其删除。setState导致错误消失

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

但是我不能删除这行,因为我需要更新这个组件的状态

我有这个错误,原来是我无意中包括一个对象在我的JSX代码,我曾期望是一个字符串值:

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

breadcrumbElement曾经是一个字符串,但是由于重构而变成了一个对象。不幸的是,React的错误消息并没有很好地将我指向存在问题的行。我必须一直跟踪堆栈,直到我识别出"props"被传递到组件中,然后我找到了有问题的代码。

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

所以当我试图显示createdAt属性是一个日期对象时,我得到了这个错误。如果像这样在末尾连接.toString(),它将进行转换并消除错误。只是把这个作为一个可能的答案,以防其他人遇到同样的问题:

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

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

{{count}}

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

{count}

,编译器可能会把它变成{{count: count}},即试图插入一个对象作为React的子对象。

只是想我会添加到这个,因为我今天有同样的问题,原来是因为我只是返回函数,当我把它包装在一个<div>标签它开始工作,如下

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

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

修复了这个问题
return (
  <div>
    {gallerySection}
  </div>
);

…或者仅仅是:

return gallerySection

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. 没有错误:与对象的属性(应该是原始的,即字符串值或整数值)传递给子。

    <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 vs this.props.name).

Source - codingbismuth.com

我的原因是忘记了在发送给表示组件的props周围加上花括号:

:

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

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

我也得到这个"对象是无效的作为一个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团队正在开发一个解决方案。

我的问题是在render()函数的返回语句中,不必要地在包含HTML元素的变量周围加上花括号。这使得React把它当作一个对象而不是一个元素。

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

一旦我从元素中去掉花括号,错误就消失了,元素被正确呈现。

对于任何在Android上使用Firebase的人来说,这只会破坏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

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

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

通常这是因为你没有正确地解构。以以下代码为例:

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

…这工作。

很有可能,任何偶然发现这一点的人只是不小心声明了他们组件的props参数而没有解构。

只需去掉return语句中的花括号。

:

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

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

在我的情况下,我忘记从渲染函数返回一个html元素,我正在返回一个对象。我所做的只是用html元素包装了{items} -一个简单的div,就像下面的

<ul>{items}</ul>

我也有同样的问题,因为我没有把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>
    );
}

我得到了同样的错误,我改变了这个

export default withAlert(Alerts)

到this

export default withAlert()(Alerts) .

在旧版本中,前面的代码是可以的,但在后来的版本中,它抛出一个错误。所以使用后面的代码来避免错误。

这是我代码:

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

希望这能帮助到一些人!

如果由于某种原因您导入了firebase。然后尝试运行npm i --save firebase@5.0.3。这是因为firebase中断react-native,所以运行这个将修复它。

只需删除组件中的async关键字。

const Register = () => {

此后无问题。

在我的例子中,我向子函数组件添加了一个async,并遇到了这个错误。不要对子组件使用async。

当我在FlatList中调用renderItem函数async时,我得到了这个错误。

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

我的案例在使用reduce时很常见,但这里没有分享,所以我把它贴出来了。

通常,如果你的数组看起来像这样:

[{ value: 1}, {value: 2}]

并且您想要在此数组中呈现value的总和。JSX代码如下所示

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

问题发生时,你的数组只有一个项目,例如:[{value: 1}]。(通常,当你的数组是来自服务器的响应时,这种情况会发生,所以你不能保证数组中的项目数量)

当数组只有一个元素时,reduce函数返回元素本身,在这种情况下它是{value: 1}(一个对象),它导致不变性违反:对象作为React子错误无效。

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

更多细节可在这里找到: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>

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

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

是的,我知道。我也在这上面浪费了45分钟。

当您尝试将对象呈现为子元素时可能会发生这种情况,您可以通过查找以下场景来找出根本原因:

  1. 检查您是否在JSX - <span>{{value}}</span>中使用任何双括号并将其更改为<span>{value}</span>(我犯了这个错误,因为我刚刚从Angular移动到React)。

  2. 检查像下面这样用大括号括起来的返回语句,并删除它。

     render() {
       let element = (
        <span>text</span>
       );
       return (
        {element}  // => Remove this extra brace
       )
     }
    
  3. 检查您在JSX中使用对象的任何其他无意方式

     let nestedObjected = {
        a : '1',
        b : {
           c: '2'
        }
     };
     {Object.keys(nestedObjected).map((key) => {
        return (
            <div>
               <span>{nestedObjected[key]}</span>  // This will cause issue since it will resolve to an object
            </div>
        );
      })}
    

我刚刚让自己犯了一个非常愚蠢的错误,我不妨在这里分享给后代。

我有一些像这样的JSX:

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

我需要把这个注释掉来调试一些东西。我在IDE中使用了键盘快捷键,结果如下:

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

当然是无效的——对象作为react的子对象是无效的!

我想在这个列表中添加另一个解决方案。

规格:

  • "反应":"^ 16.2.0",
  • "react-dom":"^ 16.2.0",
  • "react-redux":"^ 5.0.6",
  • "react-scripts":"^ 1.0.17",
  • "终极版":"^ 3.7.2章"
我遇到了同样的错误:

未捕获错误:对象作为React子对象(found: object)无效与键{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值放入分派中时,一切都开始按预期工作。

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

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

我也有同样的问题,我更新了redux状态,新的数据参数与旧的参数不匹配,所以当我想通过这个错误访问一些参数时,

也许这段经历对某人有帮助

当我面临以下错误时,我的问题很简单:

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

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

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

这似乎对我有用

相关内容

最新更新