34

I have a website built with react, which uses react-router. For some route I want to serve another page or static file, but since all request are forwarded to react router, its doesn't work.

for example

www.myapp.com/sitemap.xml
www.myapp.com/something.html

^ these link works first time, but once i load website then it doesn't work, as all request goe through react router.

Any solution to make it work all the time. Thanks.

Edit

I'm using apache server which is configured to redirect all request to index.html, i guess this is the reason for this behaviour. This is my configuration, but i don't know how to fix this.

Options -MultiViews
RewriteEngine On

RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

Update I tried solution suggested in answer.

my routes looks like this, for something.html i am loading ServerLoad component

<Switch>
    <Route exact path="/" component={Home} />
    <Route path="/about" component={About} />
    <Route path="/about" component={About} />
    <Route path="something.html" component={ServerLoad} />
    <Route component={NoMatch} />
</Switch>

In ServerLoad component's componentDidMount function I did this. But it doesn't work.

componentDidMount() {
    window.location.reload(true);
}

More I have setup this project using create-react-app, and serving it by express server(like this). I'am not sure if i need to do some setting there to server other static files.

Abhishek
  • 1,694
  • 2
  • 16
  • 27

7 Answers7

14

This should work:

const reload = () => window.location.reload();

<Router>
  // all your routes..
  ...

  // Your special routes..
  <Route path="/sitemap.xml" onEnter={reload} />
  <Route path="/something.html" onEnter={reload} />
</Router>

So, I think this should be pretty clear what it does ;)

Update:

if this is an option you can simply put target="_blank" attribute in your <Link>

IMHO this is from the UX perspective even better, because if these routes are not part of your main application, the user can just switch the Tab after visiting that special pages.

webdeb
  • 12,993
  • 5
  • 28
  • 44
  • 1
    Hi, I tried this, check update in question. It doesn't work – Abhishek Aug 31 '17 at 12:42
  • Ok So this solution works, but it might not work `properly` if you have service worker registered. Because Create-React-App support this feature out of box so it was enabled in my site. I have disabled service worker and now it works. – Abhishek Sep 02 '17 at 11:16
  • Thank you @webdeb – Abhishek Sep 02 '17 at 11:17
  • glad to help.. could you dive deeper into the problem with the service worker? Would be interesting to know whats the difference when a service worker is running.. – webdeb Sep 02 '17 at 12:09
  • 1
    yes i plan to do so, but right now my schedule is tight. I will update. – Abhishek Sep 02 '17 at 13:07
  • Where do you save the file in the project folder? I'm trying to save at public and it's copying to the build folder, but when I serve the build it's getting 404 by react-router. – 7xRobin Sep 18 '20 at 14:04
5

How about simply put your statics files like sitemap.xml inside React's public folder along side index.html.

I thinks this is the easiest way.

enter image description here

Nico
  • 858
  • 10
  • 20
4

It's an unwanted behaviour of ServiceWorker.js use the comment below and change it in index.js of your React project (if you don't need a service worker) and it should work

import { unregister } from './registerServiceWorker';
unregister();

https://github.com/facebookincubator/create-react-app/issues/2715

If you still need a service worker and you want to avoid it having this behavior, consider installing a custom service worker, there you can establish a whitelist of paths to be ignored. For more information you can check the next link.

https://medium.com/swlh/how-to-implement-custom-service-worker-in-create-react-app-without-eject-bfa2c5f4ae96

Angelo Giuseppe
  • 85
  • 1
  • 1
  • 9
1

Use Switch combined with a NoMatch component, combined with webdeb's solution:

<Router>
  <div>
    <Switch>
      <Route exact path="/" component={Home} />
      <Route exact path="/admin" component={Admin} />
      <Route component={NoMatch} />
      <Route onEnter={() => window.location.reload()} />
    </Switch>
  </div>
</Router>

This will match routes, show 404 if no valid href exists, and show a file or something if it's a valid href.

corysimmons
  • 7,296
  • 4
  • 57
  • 65
1

If you need /terms to redirect to /terms.html, the code below worked for me with react-router 3.x.

const reload = () => window.location.reload();
<Router>
  <Switch>
    <Route exact path="/" component={Home} />                
    <Route path="/terms.html" render={reload} />
    <Route path="/privacy.html" render={reload} />
    <Route path="/terms" render={() => <Redirect
        to={{
          pathname: "/terms.html"
        }}
      />} 
    />
    <Route path="/privacy" render={() => <Redirect
        to={{
          pathname: "/privacy.html"
        }}
      />} 
    />
  </Switch>
</Router>
dsunku
  • 503
  • 5
  • 9
0

1. Create folders for each HTML file inside the public folder.

enter image description here

2. Add route paths (path= name_of_folder_contained_static_file)

enter image description here

3. Call route paths as you want :)

Demo:

enter image description here

enter image description here

enter image description here

Lojith Vinsuka
  • 906
  • 1
  • 10
  • 8
-1

If the pages are unrelated to the Reactjs App at all(i.e. using another directory), I think we can route it from Node layer using the following code, so that the structure is more intuitive:

app.use('/url_to_static_pages', express.static('path_to_static_files'));
Eric Tan
  • 1,377
  • 15
  • 14