react-router: Not found (404) for dynamic content? react-router: Not found (404) for dynamic content? reactjs reactjs

react-router: Not found (404) for dynamic content?


First of create a middleware function for the onEnter callback, so that this is workable for redux promises:

import { Router, Route, browserHistory, createRoutes } from "react-router";function mixStoreToRoutes(routes) {    return routes && routes.map(route => ({        ...route,        childRoutes: mixStoreToRoutes(route.childRoutes),        onEnter: route.onEnter && function (props, replaceState, cb) {            route.onEnter(store.dispatch, props, replaceState)                .then(() => {                    cb(null)                })                .catch(cb)        }    }));}const rawRoutes = <Route path="/">    <Route path="user/:userId" component={UserPage} onEnter={userResolve.fetchUser} />    <Route path="*" component={NotFound}  status={404} /></Route>

Now in this onEnter function you can work directly with the redux store. So you could dispatch an action that either successes or fails. Example:

function fetch(options) {    return (dispatch) => {        return new Promise((resolve, reject) => {            axios.get('<backend-url>')                .then(res => {                    resolve(dispatch({type: `CLIENT_GET_SUCCESS`, payload: res.data}))                })                .catch(error => {                    reject(dispatch({type: `CLIENT_GET_FAILED`, payload: error}));                })            }        })    }}let userResolve = {    fetchUser: (dispatch, props, replace) => {        return new Promise((next, reject) => {            dispatch(fetch({                user: props.params.user            }))                .then((data) => {                    next()                })                .catch((error) => {                    next()                })        })    }}

Whenever the resolve promise now fails, react-router will automatically look for the next component that it could render for this endpoint, which in this case is the 404 component.

So you then wouldn't have to use replaceWith and your URL keeps retained.


If you are not using server side rendering, returning 404 before the page gets rendered would not be possible. You will need to check for the existence of the user somewhere either way (on the server or via AJAX on the client). The first would not be possible without server side rendering.

One viable approach would be to show the 404 page on error of the Promise.


I tried my solution in a project that I am making which uses Server Side Rendering and react-router and it works there, So I'll tell you what I did.

Create a function in which you'll validate an ID. If the ID is valid, Then return the with User page with proper Component, If the ID is invalid then return the with 404 Page.

See the example:

// Routes.jsx

function ValidateID(ID) {    if(ID === GOOD_ID) {        return (            <Route path="/">                <Route path="user/:userId" component={UserPage} />                <Route path="*" component={NotFound}  status={404} />            </Route>        );    } else {       return (           <Route path="/">               <Route path="user/:userId" status={404} component={Page404} />              <Route path="*" component={NotFound}  status={404} />           </Route>       );    }

// Router.jsx

<Router route={ValidateID(ID)} history={browserHistory}></Router>

This should work with Server Side rendering as it did in my project. It does not uses Redux.