Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 Failed propType #6

Closed
badtant opened this issue Jul 17, 2015 · 5 comments
Closed

ES6 Failed propType #6

badtant opened this issue Jul 17, 2015 · 5 comments

Comments

@badtant
Copy link

badtant commented Jul 17, 2015

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
};
@danharper
Copy link

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

@badtant badtant closed this as completed Jul 17, 2015
@gaearon
Copy link
Contributor

gaearon commented Jul 17, 2015

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)

@blesswinsamuel
Copy link

blesswinsamuel commented Aug 5, 2016

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

@joshmanderson
Copy link

joshmanderson commented Aug 17, 2016

@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

@joshmanderson
Copy link

joshmanderson commented Aug 17, 2016

@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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants