【问题标题】:Invariant Violation: Objects are not valid as a React childInvariant Violation:对象作为 React 子对象无效
【发布时间】:2022-01-14 00:12:02
【问题描述】:

在我的组件的渲染函数中,我有:

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

一切正常,但是当单击&lt;li&gt; 元素时,我收到以下错误:

未捕获的错误:不变违规:对象作为 React 无效 孩子(找到:对象与键 {dispatchConfig,dispatchMarker, nativeEvent, 目标, currentTarget, 类型, eventPhase, 气泡, 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的渲染方法。

如果我在 map 函数中将 this.onItemClick.bind(this, item) 更改为 (e) =&gt; onItemClick(e, item),一切都会按预期工作。

如果有人能解释我做错了什么并解释为什么我会得到这个错误,那就太好了

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

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

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

【问题讨论】:

  • 那么this.onItemClick是如何实现的呢?
  • @zerkms 感谢回复,我更新了问题,是的,问题似乎出在this.setState(),但是为什么会抛出这个错误? :(
  • 如果你把async放在函数组件上也会发生这种情况
  • 最好不要在渲染方法中使用bind。当您在渲染函数中使用bind 时,会发生在调用渲染方法时会创建onItemClick 的新实例。因此,您可以使用箭头函数语法或在构造函数中绑定您的方法。您可以在官方指南reactjs.org/docs/handling-events.html中找到更多详细信息。
  • 感谢@PetrosKyriakou。我错误地使我的 render() 方法异步。你摇滚!

标签: javascript reactjs


【解决方案1】:

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

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

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

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

【讨论】:

  • 那么,如果你确实有一个对象,你会如何将它转换成想要的东西?
  • 您需要引用作为字符串值的对象的属性,或者将对象转换为所需的字符串表示形式。如果您真的想查看 Object 的内容,一个选项可能是 JSON.stringify。
  • 遇到了同样的错误,这个解释解决了我的问题。 1 UP 为此。 :)
  • 啊,我遇到了错误消息指向错误行的相同问题 - 它说错误出现在 this.setState({items: items}) 中,而实际上它在我的位置进一步爆炸试图使用 {this.state.items} 显示该变量。 JSON.stringify 修复了它!
  • 对于未来的读者:不,不要转换为字符串。改为这样做: const Lcomponent = this.whateverReturnsObject();然后在 render(){ return } 这就是它。
【解决方案2】:

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

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

【讨论】:

  • 宾果游戏!我遇到了这个问题,但是因为显示它的表会加载(和重新加载)就好了,所以我偏离了轨道。当我添加一行时,React 只会抛出objects are not valid 不变违规。原来我在持久化之前将 Date() 对象转换为字符串,因此只有我的新行具有创建日期的对象。 :( 向我任性的榜样学习!
  • 一种更广泛的方法是在组件的选择逻辑中使用三元语句,请参阅我对我在这里一直遇到的类似问题的回答stackoverflow.com/a/59108109/1483143
  • 我肯定有这个问题。我使用的是 DevExtreme 的 React Grid,它不喜欢我的对象数组中的 date 属性。立即使用 .toString() 将其转换为字符串。
【解决方案3】:

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

{{count}}

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

{count}

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

【讨论】:

  • {{}} 的用途/
  • @MuneemHabib 这只是 ES6 语法。 React 需要一对{}。内部对被视为 ES6 代码。在 ES6 中,{count}{count: count} 相同。所以当你输入{{count}}时,它和{ {count: count} }完全一样。
  • 有这个错误——这就是问题所在。在将我的变量分配给构造函数中的状态时,我有 this.state = {navMenuItems: {navMenu}}; ... 这基本上将我的 JSX navMenu 变成了一个通用对象。更改为 this.state = {navMenuItems: navMenu}; 消除了对 Object 的无意“强制转换”并解决了问题。
  • 我猜你来自 Angular 世界:D
  • 在前端技术中跳跃,这是我的问题。现在太明显了!谢谢
【解决方案4】:

只是想我会添加这个,因为我今天遇到了同样的问题,原来是因为我只返回了函数,当我将它包装在 &lt;div&gt; 标记中时它开始工作,如下所示

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

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

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

...或者简单地说:

return gallerySection

【讨论】:

  • 或者如果你想避免额外的div,你可以简单地使用return gallerySection
  • 返回 gallerySection 而不是 &lt;div&gt;{gallerySection}&lt;/div&gt; 帮助了我。
【解决方案5】:

React child(singular) 应该是 primitive 数据类型而不是对象或 它可能是 JSX 标签(在我们的例子中不是)。在开发中使用 Proptypes 包来确保进行验证。

只是一个快速的代码 sn-p(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; (来自下面的源代码):确保您在 JSX 中呈现的所有项目都是原语,而不是使用 React 时的对象。发生此错误通常是因为参与调度事件的函数被赋予了意外的对象类型(即在您应该传递字符串时传递对象)或组件中的 JSX 的一部分未引用原语(即 this.props vs this.props.name)。

来源 - codingbismuth.com

【讨论】:

  • 此链接不再有效,但是我发现您的答案结构在我的用例中是最有用的。此错误在 web 和 react 原生环境中都可能产生,并且在尝试使用异步生命周期对组件内的对象数组进行 .map() 时,通常会作为生命周期错误发生。我在使用 react native react-native-scrollview 时遇到了这个线程
  • 很高兴,您发现它很有用,并感谢您标记链接问题。
  • 这对我有帮助。返回属性而不是对象:return &lt;p&gt;{item.whatever}&lt;/p&gt;;
【解决方案6】:

我的问题与忘记发送到演示组件的道具周围的花括号有关:

之前:

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

之后

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

【讨论】:

  • 我的问题和你的最相似,所以应用你的解决方案对我有帮助。 +1,谢谢!
【解决方案7】:

我的问题是在 render() 函数的 return 语句中不必要地将大括号括在包含 HTML 元素的变量周围。这使得 React 将其视为对象而不是元素。

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

  return (
    {element}
  )
}

一旦我从元素中删除了花括号,错误就消失了,并且元素被正确渲染了。

【讨论】:

  • 谢谢!从元素中删除花括号也对我有用!
【解决方案8】:

我也收到了这个“对象作为 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 团队正在研究解决方案as documented here

【讨论】:

  • 你应该做的是在数据进入时更新状态,然后使用状态值渲染组件
  • 你应该做的是在数据进入时更新状态,然后使用状态值渲染组件
【解决方案9】:

对于在 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

【讨论】:

  • 对于尝试下面 KNDheeraj 提出的解决方案的任何人,如果您使用 Firebase 项目中的任何文件,请 **** 1 票否决。然后只需将 import firebase 语句放在最后!我知道这听起来很疯狂,但试试吧!! **************** 我确实尝试过,这不是 iOS 的解决方案,但仅适用于 Windows 上的 Android。
【解决方案10】:

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

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

}

【讨论】:

  • 哇,这对我有帮助,我不明白你为什么要访问对象个体
【解决方案11】:

这通常是因为您没有正确解构而弹出。以这段代码为例:

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

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

我们使用= text =&gt; 参数声明它。但实际上,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" />
)

...有效。

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

【讨论】:

  • 这应该显示为正确答案,新手错误;)
【解决方案12】:

只需删除 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
}

【讨论】:

    【解决方案13】:

    我遇到了同样的问题,因为我没有将 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 我认为即使在这个小缩进之前就已经很好理解了
    • 我没有说不是。我认为您的答案在缩进中看起来更好。如果您不同意,请随时回滚。
    【解决方案14】:

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

    export default withAlert(Alerts)

    到这里

    export default withAlert()(Alerts).

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

    【讨论】:

      【解决方案15】:

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

      【讨论】:

        【解决方案16】:

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

        &lt;ul&gt;{items}&lt;/ul&gt;

        【讨论】:

          【解决方案17】:

          这是我的代码:

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

          希望这对某人有所帮助!

          【讨论】:

            【解决方案18】:

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

            【讨论】:

              【解决方案19】:

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

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

              【讨论】:

              • 导航调用的异步函数引起了同样的问题
              【解决方案20】:

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

              const Register = () => {
              

              在此之后没有问题。

              【讨论】:

                【解决方案21】:

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

                更多详情可以在这里找到: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>

                【讨论】:

                  【解决方案22】:

                  在我的情况下,我有同样的问题, 我更新了redux状态,新的数据参数和旧的参数不匹配,所以当我想通过这个Error访问一些参数时,

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

                  【讨论】:

                  • 就我而言,(Django) ListSerializer 和 CreateSerializer 返回相同的字段,其中一些(取决于您的项目)只是只读字段,因此每次创建新数据时都只需简单地更新还原状态
                  【解决方案23】:

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

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

                  是的,我知道。我也为此浪费了 45 分钟。

                  【讨论】:

                  • 谢谢。它解决了我的 firebase (5.9.2) 问题:)
                  【解决方案24】:

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

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

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

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

                  &lt;div&gt;{array.reduce((acc, curr) =&gt; acc.value + curr.value)}&lt;/div&gt;

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

                  reduce 代码行将立即返回数组内唯一的一个元素,它是一个对象,它会导致错误。

                  【讨论】:

                    【解决方案25】:

                    我只是让自己经历了这个错误的一个非常愚蠢的版本,我不妨在这里分享给后代。

                    我有一些这样的 JSX:

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

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

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

                    这当然是无效的——对象作为反应子级无效!

                    【讨论】:

                      【解决方案26】:

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

                      规格:

                      • “反应”:“^16.2.0”,
                      • "react-dom": "^16.2.0",
                      • "react-redux": "^5.0.6",
                      • “反应脚本”:“^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 值放入调度时,一切都开始按预期工作。

                      【讨论】:

                        【解决方案27】:

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

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

                        【讨论】:

                          【解决方案28】:

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

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

                          【讨论】:

                            【解决方案29】:

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

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

                            这似乎对我有用

                            【讨论】:

                              【解决方案30】:

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

                              我写道:

                              {response.isDisplayOptions &&
                              {element}
                              }
                              

                              将它放在一个 div 中修复它:

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

                              【讨论】:

                                猜你喜欢
                                • 2017-02-09
                                • 1970-01-01
                                • 2019-08-18
                                • 2019-03-09
                                • 2019-07-20
                                相关资源
                                最近更新 更多