• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
    • Questions
    • Teachers
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

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

How can react-router properly handle 404 pages for dynamic content in a Universal app?

Let's say I want to display a user page with a route like '/user/:userId'. I would have a config like this:

<Route path="/">
    <Route path="user/:userId" component={UserPage} />
    <Route path="*" component={NotFound}  status={404} />
</Route>

If I request /user/valid-user-id, I get the user page.

If I request /foo, I get a proper 404.

But what if I request /user/invalid-user-id. When fetching the data for the user, I will realize that this user does not exist. So, the correct thing to do seams to be:

  • Display the 404 page
  • Return a 404 http code (for server side rendering)
  • Keep the url as is (I don't want a redirect)

How do I do that?? It seams like a very standard behaviour. I'm surprised not to find any example...

Edit:
Seams like I'm not the only one to struggle with it. Something like this would help a lot: https://github.com/ReactTraining/react-router/pull/3098
As my app won't go live any time soon, I decided to wait to see what the next react-router version has to offer...

almost 3 years ago · Santiago Trujillo
3 answers
Answer question

0

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.

almost 3 years ago · Santiago Trujillo Report

0

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.

almost 3 years ago · Santiago Trujillo Report

0

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.

almost 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error