Search code examples
javascriptreactjsreact-router-v4react-context

React-router-V4 render error when using ReactJS new context API


I´m trying to use React Router V4 with new React´s context API. Here is my code:

class App extends Component {
    static propTypes = {
        router: PropTypes.func.isRequired,
        module: PropTypes.string.isRequired,
        sideMenuConfig: PropTypes.string
    };

    render() {

        let baseName = "/" + this.props.module;

        // This will get my dashboard component, loading context from database
        let navComponent = (
            <MyCustomAppContextProvider>
                <AppContext.Consumer>
                    {context => 
                        <Dashboard
                            context={context}
                            module={this.props.module}
                            router={router}
                            sideMenuConfig={this.props.sideMenuConfig}
                        />
                    }
                </AppContext.Consumer>
            </MyCustomAppContextProvider>
            );

        let routes = null;
        if (!isAuthenticated()) {
            routes = <Auth 
                        baseName={baseName}
                     />;
        } else {
            routes = (
                <Switch>
                    <Route exact path="/logout" component={Logout} />
                    <Route exact path="/auth" component={Logout} />
                    <Route exact path="/" component={navComponent} />
                    <Route
                        exact
                        path="/:screen"
                        component={navComponent}
                    />
                    <Route
                        exact
                        path="/:screen/:action"
                        component={navComponent}
                    />
                    <Route
                        exact
                        path="/:screen/:action/:id"
                        component={navComponent}
                    />

                    <Route component={PageNotFoundError} />
                </Switch>
            );
        }

        return (
            <BrowserRouter basename={baseName}>
                {routes}
            </BrowserRouter>
        );
    }
}

export default App;

router contains a router function that will load my screen depending on the navigation path.
module is the module name.
sideMenuConfig is a json configuration for my side menu.

When trying to run I´m getting the following error from react router:

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

Check the render method of `Route`.

I expect in Dashboard to receive all the props passed plus the match property to run the router.


Solution

  • The problem is that you're not passing a component to Route

    // THIS IS NOT A COMPONENT
    
    let navComponent = (
      <MyCustomAppContextProvider>
        <AppContext.Consumer>
          {context => (
            <Dashboard
              context={context}
              module={this.props.module}
              router={router}
              sideMenuConfig={this.props.sideMenuConfig}
            />
          )}
        </AppContext.Consumer>
      </MyCustomAppContextProvider>
    )
    

    A component is either a class that extends React.Component or a function:

    // THIS IS A COMPONENT 
    
    let NavComponent = props => (
      <MyCustomAppContextProvider>
        <AppContext.Consumer>
          {context => (
            <Dashboard
              context={context}
              module={this.props.module}
              router={router}
              sideMenuConfig={this.props.sideMenuConfig}
            />
          )}
        </AppContext.Consumer>
      </MyCustomAppContextProvider>
    )
    

    UPDATE to your UPDATE:

    You're getting confused about what is a component

    // THIS IS A COMPONENT
    let Foo = props => <div />
    
    // THIS IS NOT A COMPONENT
    let Foo = <div />
    

    You need to pass a component to Route's component prop:

    let NavComponent = props => <MyCustomAppContextProvider>...
    
    // YES
    <Route component={NavComponent} />
    
    // NO
    <Route component={<NavComponent />} />