React-redux: connect() returns an object

Created on 2 Jun 2019  路  9Comments  路  Source: reduxjs/react-redux

I'm using these libraries:

react: 16.8.6
redux: 4.0.1
react-redux: 7.0.3

I have a simple component (Typescript):

class ExampleComponent extends React.PureComponent<IProps, {}> {
    constructor(props: any) {
        super(props);
    }

    public render() {
        return (
            <div>
                {this.props.name}
            </div>
        );
    }
}

interface IProps{
    name: string;
}

const mapStateToProps = (state) => {
    return {
        name: state.name
    };
}

export default connect(mapStateToProps)(ExampleComponent);

And I have a parent component:

import ExampleComponent from './ExampleComponent';

export default class App extends React.PureComponent<{}, {}> {
    constructor(props: any) {
        super(props);
    }

    public render() {
        return (
            <div>
                <ExampleComponent />
            </div>
        );
    }
}

For some reason the connect(mapStateToProps)(ExampleComponent) returns an object instead of React component.
I am getting an error:

Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function but got: object

Also when I trying to do console.info(typeof connect(mapStateToProps)(ExampleComponent)) it prints object to the console.

How can I solve this issue?

Most helpful comment

Hello guys, I've found a solution to make it work with the old react-router and I suppose this should also work other outdated libraries. The solution is just to wrap the returned memorized component with a stateless component which isn't enhanced by memo:

const NonMemorizedNotFoundErrorPage = props => <NotFoundErrorPage {...props} />;
...
<Route path="/*" component={NonMemorizedNotFoundErrorPage} />

All 9 comments

Yes, as of React-Redux v7, connect() uses React.memo(), which actually returns a special object as a component type rather than a function.

Also, please make sure that you don't have duplicate copies of React in your tree, and that React truly is on React 16.8.x.

Thanks for the rapid assistance!

In the npm list command I can see that +-- [email protected]

Isn't it enought?

Should be, yes.

If you can create a sample project that reproduces the issue (preferably as a CodeSandbox), I can maybe take a quick look.

Thanks to CodeSandbox I found that the problem is with react-dom library. It was set to 16.4.xx by mistake so it didn't know how to handle those objects. Upgrading to 16.8.xx solved the problem.
Thanks!

@markerikson is there any way to turn it off? I use the old react-router and it warns "Invalid prop component supplied to Route.".

@finom : no. connect() in React-Redux v7 uses React.memo(), and that's not changing. In addition, any code that assumes components are _only_ functions has been wrong since React 16.6 came out.

If you're using an older version of React-Router, you need to either upgrade the router version, or stick with an older version of React-Redux.

Yes. I found this today. And it is a pretty big issue unfortunately. withStyles() from material-ui also uses this memo, breaking some of my code. Upgrading react-router is the way to go.

But I use react-router-dom 4.3.1 and it does render but I get an error in the console:
index.js:1437 Warning: Failed prop type: Invalid prop `component` of type `object` supplied to `Route`, expected `function`.

EDIT: I updated to react-router-dom 5.0.1 and now it works without errors in the console. Fixed somewhere between 4.3.1 and 5.0.1 of react-router-dom.

Hello guys, I've found a solution to make it work with the old react-router and I suppose this should also work other outdated libraries. The solution is just to wrap the returned memorized component with a stateless component which isn't enhanced by memo:

const NonMemorizedNotFoundErrorPage = props => <NotFoundErrorPage {...props} />;
...
<Route path="/*" component={NonMemorizedNotFoundErrorPage} />

Yes. I found this today. And it is a pretty big issue unfortunately. withStyles() from material-ui also uses this memo, breaking some of my code. Upgrading react-router is the way to go.

But I use react-router-dom 4.3.1 and it does render but I get an error in the console:
index.js:1437 Warning: Failed prop type: Invalid prop `component` of type `object` supplied to `Route`, expected `function`.

EDIT: I updated to react-router-dom 5.0.1 and now it works without errors in the console. Fixed somewhere between 4.3.1 and 5.0.1 of react-router-dom.

It seems to be fixed in 5.0.0 as per the release notes and this version did fix the issue for me.

Was this page helpful?
0 / 5 - 0 ratings