How to render NotFound Component react-router-config

Viewed 3789

I am new to react I would like to implement server side rendering with react router 4 I am using this package react-router-config to write plain routes But I don't why not found component is not rendering it always access the parents routes and in parent routes if user not authenticated they will redirected .Not found is not rendering as expected

enter image description here

Code

import Home from './containers/Home';
import PrivateLayout from './containers/PrivateLayout';
import NewTest from './containers/NewTest'
import TestBoard from './containers/TestBoard';
import Profile from './containers/Profile';
import NotFound from './containers/NotFound';
import PublicLayout from './containers/PublicLayout';
export default [
    {
        ...Home,
        path:'/',
        exact:true
    },
    {
        ...PublicLayout,
        routes:[
            {
                ...Profile,
                path:'/@:username',
                exact:true
            },
            {
                ...PrivateLayout,
                routes:[
                    {
                        ...TestBoard,
                        path:'/home',
                        exact:true

                    },
                    {
                        ...NewTest,
                        path:'/test/:username',
                        exact:true
                    }
                ]
            },


        ]
    },
    {
        ...NotFound,
    },
]

index.js

import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import Routes from './Routes';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import reduxThunk from 'redux-thunk';
import { renderRoutes } from 'react-router-config';
import { BrowserRouter ,Switch} from 'react-router-dom';
import reducers from './reducers';
import './index.css';
import axios from 'axios';
import { Map } from 'immutable';
import CONFIG from './config'

const axiosInstance = axios.create({
    baseURL:CONFIG.HOST,
    withCredentials: true
});


const INITIAL_STATE = window.INITIAL_STATE || {};

Object
    .keys(INITIAL_STATE)
    .forEach(key => {
        INITIAL_STATE[key] = Map(INITIAL_STATE[key]);
    });


const store = createStore(reducers,INITIAL_STATE, applyMiddleware(reduxThunk.withExtraArgument(axiosInstance)));

window.store = store;

ReactDOM.render(
    <Provider store={store}>
        <BrowserRouter>
            <Switch>
               <div>{renderRoutes(Routes)}</div>
            </Switch>
        </BrowserRouter>
    </Provider>
    , document.getElementById('root'));

UPDATE #1

Why different Layout ?

I have common Header (or) Logged In Header to be showed on both profile Page and private Layout Components .To be clear Profile page will displayed even user logged out But Private Layout content will not be displayed it will be redirected

Example Import

import React,{Component} from 'react';


class NotFound extends Component{
    render(){
        return(
            <h1>Not Found</h1>
        )
    }
}

export default {
    component:NotFound
}

After Updating the Zarcode Answer I got an error Like this

index.js:2177 Warning: React does not recognize the computedMatch prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase computedmatch instead. If you accidentally passed it from a parent component, remove it from the DOM element. in div (at index.js:39) in Switch (at index.js:38) in Router (created by BrowserRouter) in BrowserRouter (at index.js:37) in Provider (at index.js:36)

And HTML Render Looked Like this

enter image description here

UPDATE #2

I noticed wired Behaviour If I changed the notFound component inside the private routes it is working But the problem it is working for only Logged in Routes.

...
    {
                ...PrivateLayout,
                routes:[
                    {
                        ...TestBoard,
                        path:'/home',
                        exact:true

                    },
                    {
                        ...NewTest,
                        path:'/test/:username',
                        exact:true
                    },
                    {
                        ...NotFound,
                    },
                ]
            }
...
3 Answers

One of the route

  {
    path: '/pathanme/',
    exact: true,
    strict: true,
    check: routeService.check.auth(),
    name: 'routeName',
    component: componentName,
    cache: 0,
  }

Internally renderRoutes work like normal react-router

   <Switch {...switchProps}>
      {
        routes.map((route, i) => (
          <Route
            key={route.key || i}
            path={route.path}
            exact={route.exact}
            strict={route.strict}
            render={(props) => {
              const location = route.check && route.check(props);
              if (location) {
                props.history.push(location);
                return null;
              }
              return (
                <route.component
                  {...props}
                  {...extraProps}
                  route={route}
                />
              );
            }}
          />
        ))
      }
    </Switch>

this is, How render route working internally.

I have added a render prop in < Route > where you can right your own logic. I have passed one more property from route called check where I'm checking that user is loggedin or not. Accordingly I'm loading component.

Related