反应错误 - 无法分配给对象“#<Object>”的只读属性“validated”

Phi*_*den 1 reactjs

我有以下组件:

export const Alert = (props: {message: string, type?: AlertType, createAgainButton?: Object} ) =>
{

const type = props.type || 'Message'

switch(type)
    {
        case 'Warning':
            return (
                <div className='tgg-alert-danger'>
                    <div className='tgg-alert-icon'><Icon name='exclamation-circle'/></div>
                    <div className='tgg-alert-text'>{props.message}</div>
                </div> )
        case 'Spinner':
            return (
                <div className='tgg-alert-danger'>
                    <div className='tgg-alert-icon'><Icon name='circle-o-notch fa-spin'/></div>
                    <div className='tgg-alert-text'>{props.message}</div>
                </div>)
        default:
            return (
                <div className='tgg-alert-success'>
                    <div className='tgg-alert-icon'><Icon name='check-circle'/></div>
                    <div className='tgg-alert-text'>{props.message}</div>
                    { props.createAgainButton }
                </div>)
    }
}
Run Code Online (Sandbox Code Playgroud)

对于默认情况,有时我的代码会引发以下 React 错误:

Cannot assign to read only property 'validated' of object '#<Object>'
Run Code Online (Sandbox Code Playgroud)

据报告,该错误位于 React 模块中:

TypeError: Cannot assign to read only property 'validated' of object '#

<Object>'
validateChildKeys
node_modules/react/cjs/react.development.js:1136
  1133 | } else if (isValidElement(node)) {
  1134 |   // This element was passed in a valid location.
  1135 |   if (node._store) {
> 1136 |     node._store.validated = true;
  1137 |   }
  1138 | } else if (node) {
  1139 |   var iteratorFn = getIteratorFn(node);
Run Code Online (Sandbox Code Playgroud)

我不知道为什么。我尝试将倒数第二个表达式更改为:

{ props.createAgainButton && props.createAgainButton }
Run Code Online (Sandbox Code Playgroud)

在本例中,这是我使用警报组件的地方:

// @flow
import React  from 'react'
import {connect} from 'react-redux'
import {Alert} from '../../ui/coreUIComponents'
import type {AlertType} from '../misc/types'

const mapStateToProps = (state) => {
    return {
        message: state.alert.message,
        danger: state.alert.danger,
        createAgainButton: state.alert.createAgainButton
        }
}

export default connect(mapStateToProps)(

    (props: {message: string, danger: boolean, createAgainButton?: Object}) =>
    {
        window.scrollTo(0,0);                                    
        const type: AlertType = props.danger? "Warning" : "Message"

        return (
            props.message ? <div>
                { props.createAgainButton ?
                    <Alert message={props.message} type={type} createAgainButton={props.createAgainButton} />
                :
                    <Alert message={props.message} type={type}  />
                }
            </div>
            :
                <div></div>
        )
    }
)
Run Code Online (Sandbox Code Playgroud)

我想知道我是否做错了什么明显的事情。该警报在异步调用上传数据后显示。有时,它需要显示一个按钮来创建另一条记录。该功能由封装底层记录组件的 HoF 提供。它对某些人有效,但对其他人无效。有任何想法吗?

菲尔

小智 7

我知道这是一个老问题,但也许现在有人发现它。我们的代码库中也发生了类似的事情。我只想提一下我们的原因是什么。

react简而言之,状态中存储了JSX 元素,我们使用immer的本质上是深度冻结存储中的所有内容,因此该component._store属性也设置为只读 - 这导致 React 的开发版本在子键验证上失败步。

正如我所看到的,您还将 createAgainButton 存储在某处,也许它来自商店,其中您的中间件之一可能使其不可变。

解决方案:不要将 JSX 存储在您的商店中。如果必须,那就不要使用immer,但是如果你想,那就不要使用 的开发版本react