3

I am developing a react app with react router with a server hosting both the react app itself and a REST API. The router is ConnectedRouter from react-router-redux. As I understand, once you have opened the app in your browser, any changes to the URL will not be requested from the server but instead handled client-side in react router, even if you reload the page or write something manually into the address bar.

When first opening the app, the actual HTML, JS and CSS files are loaded from the web server, which is configured to only serve them if the user is authorized. This way, the server can redirect the user to a third-party authentication site, or serve a 401 message if the user is authenticated but not authorized. However, the problem occurs when the user session expires, he logs out or his permissions change so that he's no longer authorized to open the app. Then when the user opens the app on a browser that has previously cached it, it appears to open as normal, but with lots of errors because every API call now fails.

To solve this I would like to, when the API calls fail, tell the user to reload the page so that a request is made to the server to fetch the app (index.html, etc), so that he gets redirected to the third party authentication site. However a regular browser reload (F5) doesn't cut it. The request is swallowed by react-router, and never hits the server. This is also the case with window.location.reload(). A hard reload, i.e. Ctrl+F5 seems to do the trick, at least in chrome, but some users may not understand that. Thus I would like to present the user with a "hard reload" button that temporarily tells react-router to yield url requests, so that they can pass to the server and try to fetch index.html.

So my question is: How can I temporarily and programatically force the client-side app to allow URL requests to go to the server as normal, as opposed to handling them itself in react-router?

Alternatively, if this is not possible, how can I programatically purge the app from the browser's memory, so that it will be forced to request the server again?

Edit: It seems my assumption that the requests are swallowed by react-router was wrong. It was the service worker in the create-react-app framework. The service worker exposes an unregister function that solved my problem.

3
  • does your url includes #? Otherwise your server is correctly receiving requests but there may be a wildcard which always sends index.html back. Look at your Server Side Router. Commented Nov 23, 2017 at 11:48
  • Do load balancing Commented Nov 23, 2017 at 11:49
  • Hitmands, no, the URLs do not include #, which they don't need to because the server is (correctly) not receiving requests at all (they would've shown up in the request log). They are all swallowed by react router. I would like to temporarily disable this. Commented Nov 23, 2017 at 12:03

1 Answer 1

5

As I understand, once you have opened the app in your browser, any changes to the URL will not be requested from the server but instead handled client-side in react router, even if you reload the page or write something manually into the address bar.

This is not true. Upon manual change in address bar (and pressing enter), you will always first hit server router.

It is very likely that your server, no matter which url is hit, will always render your index.html which contains your React app. Something similar to this:

app.use(express.static(path.join(__dirname, 'dist')));
app.get('*', function(req, res) {
    res.sendfile('./dist/index.html');
});

Make sure your API requests do not conflict with this. If possible, share some code, so we can review what could go wrong.

Sign up to request clarification or add additional context in comments.

4 Comments

I cannot see anything in the request logs at the server. But I failed to mention that I am using the "ConnectedRouter" from react-router-redux. Maybe this works differently? My top-level react component looks like this: render() { return ( <Provider store={this.props.store}> <ConnectedRouter history={this.props.history}> <App /> </ConnectedRouter> </Provider> ); }
@ErikLothe But if your requests never get to the server and you do hard refresh, then problem might not be caused on the client, but the server. Even tho, it's strange that your server doesn't get any log related to that request? Because to render website (when you enter address into url or change it and press enter), you always must send request to the server first, otherwise you would get something like 404.
I also didn't mention that I am using the create-react-app framework. It seems that the problem was not with react but with the service worker from this framework that caches requests. This module exposes an unregister function. Seems like this was what I wanted. Thanks for the help!
Hey @Kunok can you check this question stackoverflow.com/questions/47454780/…

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.