Reputation: 2124
I have a the following component:
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>)
}
}
For the default case, sometimes my code raises the following React error:
Cannot assign to read only property 'validated' of object '#<Object>'
The error is reported to be located in a React module:
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);
And I'm not sure why. I've tried changing the penultimate expression to :
{ props.createAgainButton && props.createAgainButton }
Here's where I use the Alert component in this case:
// @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>
)
}
)
I wonder if there is anything obvious I'm doing wrong. The alert is shown after an async call to upload data. Sometimes, it needs to show a button to create another record. The functionality is provided by a HoF that wraps underlying record components. It works for some, but not others. Any ideas?
Phil
Upvotes: 1
Views: 3103
Reputation: 277
I know it's an old question, but maybe someone finds it nowadays. We had something similar happening in our codebase. I just want to mention what the cause for us was.
Briefly, there were react
JSX elements stored in the state, and we were using immer
which essentially deep-freezes everything in the store, thus the component._store
property also got set to read only - which caused the development version of react to fail on the child-key validation step.
As I can see, you're also storing the createAgainButton somewhere, maybe it's coming from the store, where one of your middlewares could have made it immutable.
Solution: Don't store JSX in your store. If you have to, then don't use immer
, but if you want to, then don't use development version of react
.
Upvotes: 7