1

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.

2
  • I think the scope of this question is too broad. Partly because unless you give more details, there are a bunch of ways to solve this problem: e.g. routing to available countries could at least be solved at the initial loading of the page. There are perhaps many more cogwheels for this to adjust. The general answer would be with good design but this answer would be of no help. Sep 7, 2019 at 20:59
  • The race conditions might be telling you that you need to synchronize these executions. Or break the execution and redirect immediately when errors happen. Or wait until all the processes have finished for solving the final state of "internalError".
    – Laiv
    Sep 9, 2019 at 13:38

2 Answers 2

1

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.

0

I would have different actions and state properties for errors, where both errors will be cleared on navigation start action ( connected-react-router push action ).

If notFound action is dispatched notFound store property is set true. If internalError action is dispatched internalError store property is set true.

There's IMO no problem with the race condition, it shows what it knows, but you should consider making that "main" request synchronous and the rest of the requests happen only when it has successfully completed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.