reactjsreduxreact-reduxhigher-order-componentsreact-redux-connect

Trying to connect an HOC


Im trying to use user roles to determine whether or not to display a component. So im trying to use an HOC to handle that functionality, but im getting an error i dont quite understand. here is the code:

import React from 'react';
import { getUserRoles } from 'modules/api/account/user/selectors';
import { connect } from 'react-redux';

const RestrictedOrFallBack = ({
    wrappedComponent,
    role,
    userRoles,
    fallback,
}) => {
    if (userRoles.includes(role)) return wrappedComponent;
    return fallback;
};

const mapStateToProps = state => ({
    userRoles: getUserRoles(state),
});

const ConnectedRestrictedOrFallback = connect(mapStateToProps)(RestrictedOrFallBack);

export { RestrictedOrFallBack };
export default ({
    role,
    fallback = () => (<div />),
}) => WrappedComponent => (
    <ConnectedRestrictedOrFallback
        role={role}
        fallback={fallback}
        WrappedComponent={WrappedComponent}
    />
);

The error im getting is: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: <Connect(RestrictedOrFallBack) />

What am I doing wrong?

EDIT: updated code according to answer

import React from 'react';
import { getUserRoles } from 'modules/api/account/user/selectors';
import { connect } from 'react-redux';
import compose from 'utility/compose';

const RestrictedOrFallBack = ({
    wrappedComponent,
    role,
    userRoles,
    fallback,
}) => {
    debugger;
    if (userRoles && userRoles.includes(role)) return wrappedComponent;
    return fallback;
};

const mapStateToProps = state => ({
    userRoles: getUserRoles(state),
});

const ConnectedRestrictedOrFallback = compose(
    connect(mapStateToProps),
    RestrictedOrFallBack,
);

export { RestrictedOrFallBack };
export default ({
    role,
    fallback = () => (<div />),
}) => wrappedComponent => ConnectedRestrictedOrFallback({
    role,
    fallback,
    wrappedComponent,
});

Solution

  • You cannot "connect" an HOC. "connect" returns an HOC itself and HOC's can only be applied to actual components.

    What you are trying to do is compose 2 HOCs to form a new HOC.

    so you would do something like:

    import { connect, compose } from 'redux';
    
    const ConnectedRestrictedOrFallback = compose(
        connect(mapStateToProps),
        RestrictedOrFallback
    );