How to effectively handle 404/500 http errors in server-side rendering web application which uses store for state

error handlingif statementreactjsredux

I'm working on a website using server-side rendering approach. I'm using React and Redux for this. Redux handles the state of the application and provides API to change the state. All asynchronous data fetching is done via Redux.

The problem is that a URL may be like example.com/news/:param where param is some dynamic parameter like a country for example. In React I have a page which is common to all news pages so because the URL path starts with news react-router will find a page for it. However, if a user enters a non-valid country 404 page should be returned. Whether a country or any other param is valid can only be determined via a request to the API service I'm using, that is using Redux actions.

Another complication is that a given page may need to make several requests to the API in order to fetch data. If param is found in the API but some other less important data is not found I don't want to display 404 page. 404 page should therefore displayed only if the "main" request to the API returns 404.

Current solution:

So far in "main" requests to the API, I tentatively switch on notFound variable. That is I suspect that a request which contains an param potentially may result in 404 because the param was not found. So if such request indeed results in 404 status then my main component in React detects that notFound is now true and shows the default Not Found page to the user.

In addition I have a variable in Redux state which is called internalError. It is set to true if some internal error occurred, often as a result of a request to API, e.g. JSON parsing error, etc. internalError is always the opposite boolean value of notFound. This way when we are in the main reducer which calculates the new values for internalError and notFound then if notFound is false then error will be true and this way we know that we need to display 500 error to the user instead of 404.

This approach has several issues:

  1. Race condition between Redux actions which set notFound to true and Redux actions that set notFound back to false.
  2. Imagine a situation when 500 error may occur due to some unimportant Promise rejection (thus setting internalError to true) but later another API request will return 404 for the requested param. So first the user will see a generic error page with 500 status then a Not Found page. It's another race condition.

I'm wondering if there's a simpler, better approach.

Best Answer

If you're working on a server side rendered app, redux and react router seem like the wrong tools for you. The reason you're having difficulty is because you're taking a reasonably state-light operation (web requests and responses) and inserting a heavy duty state management tool (Redux) inside of it.

Similarly, it seems like you're using react router, a front end route handler, when standard back end route management would suit your project fine.

You're using SPA/JAM stack tooling that is great for lightweight, single purpose views but it seems like the project is at a point where owning serverside behavior is a given. You can reimplement HTTP on top of HTTP or just use standard HTTP tooling to solve these problems.

The easiest approach would probably be to use a small express or similar lightweight web server for your project, and implement your requests as standard urls. Implementing your API calls as async requests that all need to finish before returning a single response will make a much simpler system than managing all of their states independently, like Redux allows you to.

Related Topic