React-redux: ES6 Failed propType

Created on 17 Jul 2015  Â·  5Comments  Â·  Source: reduxjs/react-redux

Hi, I'm using the connector to a ES6 class. I get my data but a warning on the propType. "Warning: Failed propType: Required prop data was not specified in Home. Check the render method of Router."

I tried enabling es7.classProperties and move to static propTypes = ... That got rid of the warning but I rather stay on ES6 and only the ES7 features that i really want (like es7.decorators). Any ideas?

@connect(state => ({
    data: state.info
}))
export default class Info extends React.Component {
    render() {
        return (
            <InfoComponent data={this.props.data}/>
        );
    }
}

Info.displayName = 'Info';
Info.propTypes = {
    data: React.PropTypes.object.isRequired
};

Most helpful comment

@blesswinsamuel In regards to your example using static propTypes...
Does that work for you? Using static propTypes as you have done there still gives me the same warning messages...

EDIT:
I got it to work correctly with no warnings using the connect decorator and static propTypes.
My problem was babel related... I had the transform-class-properties plugin listed before the transform-decorators-legacy plugin.

transform-decorators-legacy must come before transform-class-properties to be able to use the connect decorator and static propTypes together (note that there are other issues that occur, entirely unrelated to redux, if you specify the order of the plugins incorrectly).

All 5 comments

When you use the @connect() decorator, your Info class is decorated as a ConnectorDecorator component.

When you then set Info.propTypes, you’re actually setting those prop types on the Connector, not on your Info component. So React is enforcing the props in the wrong place!

Instead, use an InfoContainer. I’d say this is a best practice in general, as it keeps your Info component as a “dumb component”, keeping the connected component separate. I do this even though I use static properties.

class Info extends React.Component {
    render() {
        return (
            <InfoComponent data={this.props.data}/>
        );
    }
}

Info.displayName = 'Info';
Info.propTypes = {
    data: React.PropTypes.object.isRequired
};

@connect(state => ({
    data: state.info
}))
export default InfoContainer extends React.Component {
    render() {
        return (
            <Info {...this.props} />
        )
    }
}

Or, you could probably do this (which is less extensible)

@connect(state => ({
    data: state.info
}))
export default InfoContainer extends Info {}

Don't use inheritance please :-). I have never seen a justifiable case for it in React.
I think the easiest way out is just not to use decorators in this case.

class Info extends React.Component {
    render() {
        return (
            <InfoComponent data={this.props.data}/>
        );
    }
}

Info.displayName = 'Info';
Info.propTypes = {
    data: React.PropTypes.object.isRequired
};

export default connect(state => ({
    data: state.info
}))(Info)

How about using static propTypes inside the connected component?

@connect(state => ({
    data: state.info
}))
export default class Info extends React.Component {
    static propTypes = {
        data: React.PropTypes.object.isRequired
    }

    render() {
        return (
            <InfoComponent data={this.props.data}/>
        );
    }
}

@badtant A fix I just discovered, which allows you to use the decorator:

@connect(state => ({
    data: state.info
}))
class Info extends React.Component {
    render() {
        return (
            <InfoComponent data={this.props.data}/>
        );
    }
}

Info.WrappedComponent.displayName = 'Info';
Info.WrappedComponent.propTypes = {
    data: React.PropTypes.object.isRequired
};

export default Info;

Note the use of the static property WrappedComponent, which is "The original component class passed to connect()", and can be found in the documentation here: https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options

@blesswinsamuel In regards to your example using static propTypes...
Does that work for you? Using static propTypes as you have done there still gives me the same warning messages...

EDIT:
I got it to work correctly with no warnings using the connect decorator and static propTypes.
My problem was babel related... I had the transform-class-properties plugin listed before the transform-decorators-legacy plugin.

transform-decorators-legacy must come before transform-class-properties to be able to use the connect decorator and static propTypes together (note that there are other issues that occur, entirely unrelated to redux, if you specify the order of the plugins incorrectly).

Was this page helpful?
0 / 5 - 0 ratings