Search code examples
reactjsreact-routerreact-router-v4

Using render in react router dom with a private route


Im trying to render two components within a private route using react router dom v4. This is possible using a normal Route but it does not seem to be the case when using a custom Route. I get the following error: "Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. "

Custom route (Authenticated)
return (
      <Route
        {...rest}
        render={props =>
          this.currentUser()
            ? <Component currentUser={this.currentUser} {...props} />
            : <Redirect
                to={{
                  pathname: '/auth/login',
                  state: { from: props.location }
                }}
              />
        }
      />
    )
Then in my routes i want something like this
return (
      <div>
        <Switch location={isModal ? this.prevLocation : location}>
          <Authenticated path="/" exact component={Main} />
          <Route path="/auth/register" exact component={Register} />
          <Route path="/auth/login" exact component={Login} />
          <Authenticated
            path="/clients/:id/edit"
            render={(props) => ( // Not working as expected. Works fine using Route instead of Authenticated
              <div>
                <Main />   
                <ClientEdit />
              </div>
            )}
          />
        </Switch>
        {isModal ?
          <Authenticated
            path='/clients/new'
            component={ClientNew}
          />
        : null}
        {isModal ?
          <Authenticated
            path='/clients/:id/edit'
            component={ClientEdit}
          />
        : null}
      </div>
    );

Solution

  • In your protectedRoute component, you are not receiving or utilizing render prop which you are sending in the line:

    render={(props) => ( 
      <div>
        <Main />   
        <ClientEdit />
      </div>
    )}
    

    instead of using render send the component in component prop like :

    component={(props) => ( 
      <div>
        <Main />   
        <ClientEdit />
      </div>
    )}
    

    Also check react router's docs to see when to use component prop and when to use render prop. It would be much better if you can change your protectedRoute to handle both.