1

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

4
  • This code says nothing about the error. Where is validated? Commented Nov 29, 2017 at 13:36
  • There error 'appears' to be in a react module. Here's an extract from the error message: module: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); Commented Nov 29, 2017 at 13:38
  • Could you share where you used that Alert component please ? Commented Nov 29, 2017 at 13:41
  • Yup - just added it to the main question Commented Nov 29, 2017 at 13:45

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

2 Comments

God, Immer is the culprit in my case too.
Thank you. I can't imagine how much time I would have spent on this debug.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.