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

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: 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.

如果我改成this。onitemclick。绑定(this, item) to (e) => onItemClick(e, item)内的映射函数,一切都按预期工作。

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

更新1: onItemClick函数如下所示。setState会导致错误消失。

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

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


当前回答

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

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

使用对象解构,你可以这样做,也经常会看到这样的东西:

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

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

...这工作。

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

其他回答

我的错误是这样写的:

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

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

编辑:这是反应不是本机。

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

通常,如果你的数组是这样的:

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

你想要呈现这个数组中值的和。JSX代码如下所示

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

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

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

显然,正如其他人之前在这篇文章中提到的,在React JSX中的道具。children不能为Object类型。这不是你具体问题的根本原因。

如果你仔细阅读错误文本,你会看到React在试图呈现一个匹配SyntheticEvent签名的对象时产生了错误:

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,但是您的事件处理程序参数的顺序乱了。

在你的渲染方法中,你将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列在参数项之前。

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

当onItemClick(e, item)被调用时,在绑定调用期间传入的项将在触发事件之前,因此参数e将被设置为映射和绑定的项,参数item将被设置为事件。

当setState被调用时,lang将被设置为代表触发onClick事件的synticevent,当你试图在其他地方呈现this.state.lang中的值时,你将收到你所看到的不变违反错误。

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

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

}

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

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