9

So this is pretty much just the product of creat-react-app and firbase init. It works exactly as expected when I do npm start but when I upload the package to firebase, the only page I am able to hit is at the / path. Even if I switch the components, they one on the / path will be hit.

App.js file

import React, { Component } from 'react';
import './App.css';
import Ok from './Ok';
import {Route, Switch} from 'react-router-dom';
import Home from "./Home";

class App extends Component {
  render() {
    return (
            <main>
                <Switch>
                    <Route exact={true} path="/" component={Home}/>
                    <Route path="/ok" component={Ok}/>
                </Switch>
            </main>
    );
  }
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {BrowserRouter} from "react-router-dom";

ReactDOM.render((
    <BrowserRouter>
        <App />
    </BrowserRouter>), document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();

firebase.json

{
  "hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

Directory structure

.
├── build
│   ├── asset-manifest.json
│   ├── favicon.ico
│   ├── index.html
│   ├── manifest.json
│   ├── precache-manifest.ecdffa8fba4446ec939aeb81deef8a46.js
│   ├── service-worker.js
│   └── static
│       ├── css
│       │   ├── main.62e37b1d.chunk.css
│       │   └── main.62e37b1d.chunk.css.map
│       ├── js
│       │   ├── 1.c86c31d4.chunk.js
│       │   ├── 1.c86c31d4.chunk.js.map
│       │   ├── main.68e18920.chunk.js
│       │   ├── main.68e18920.chunk.js.map
│       │   ├── runtime~main.229c360f.js
│       │   └── runtime~main.229c360f.js.map
│       └── media
│           └── logo.5d5d9eef.svg
├── firebase.json
├── package.json
├── package-lock.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── README.md
└── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── Home.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    ├── Ok.js
    └── serviceWorker.js

ANSWER:

I removed the main tag from App.js and moved the BrowserRouter from index.js to App.js, wrapping the Switch tag with it

David Massey
  • 249
  • 4
  • 13
  • Does the `Ok` component exist? where's the code? – Sergio Alen Oct 23 '18 at 00:26
  • I think this is expected based on the fact that the Router is working on client side only. If you need to render server side, you could use something like react snap (https://github.com/stereobooster/react-snap) as an easy solution, otherwise you'll need to setup server rendering for your routes. Take a look here (https://stackoverflow.com/questions/44491184/react-router-does-not-work-in-production-and-surge-deployments) at the accepted answer. I think this may be your problem – Jordan Quartermain Oct 23 '18 at 00:33
  • Ok component does exist. – David Massey Oct 23 '18 at 01:18
  • Jordan, I'm trying to implement this but a little confused. I thought the Router was designed for SPA navigation. What do you mean it's only client side? – David Massey Oct 23 '18 at 01:19

1 Answers1

11

You need to make sure the rewrites are enabled in your Firebase hosting configuration to redirect all requests to your index.html file. This assumes you are using create-react-app:

{
  "hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      {"source": "/service-worker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}]}
    ]
  }
}

The init command for Firebase actually provides this is an option when creating a project.

You will need to redeploy firebase deploy to propagate the changes.

Update: With the aforementioned firebase.json hosting configuration the following index.js and App.js, I was able to successfully deploy a create-react-app with working react-router-dom routing using npm run build following by firebase deploy.

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter as Router } from "react-router-dom";

ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();

App:

import React, { Component } from 'react';
import { Route, Link, Switch } from "react-router-dom";
import './App.css';

const Home = () => <h1>Home</h1>;
const Ok = () => <h1>Ok</h1>;

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/ok">Ok</Link></li>
          </ul>
        </header>
        <main>
          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/ok" component={Ok} />
          </Switch>
        </main>
      </div>
    );
  }
}

export default App;

Hopefully that helps!

Alexander Staroselsky
  • 28,923
  • 8
  • 58
  • 75
  • I tried this with no luck, but I'm not sure if maybe my directory structure is screwed up. ive added it to the question – David Massey Oct 23 '18 at 01:14
  • Yeah it may other things but SPA navigation will not work on Firebase Hosting with that configuration – Alexander Staroselsky Oct 23 '18 at 01:15
  • could you take a look, I think my index.html might be in the wrong place? – David Massey Oct 23 '18 at 01:23
  • @DavidMassey I added a `App.js` and an `index.js` from a `create-react-app` used with the previously mentioned `firebase.json` configuration. I was successfully able to deploy the application using `npm run build` and `firebase deploy` and it routes successfully [link](https://sample-react-router-01.firebaseapp.com/). Try using the provided code, re-build and re-deploy and see if it makes a difference. If it does, it means something is wrong in your code. Your built structure is fine from what I can see. – Alexander Staroselsky Oct 23 '18 at 14:21
  • Hi @AlexanderStaroselsky, I've been trying to implement your answer in my app, but with no luck. Could you have a look at the [question](https://stackoverflow.com/questions/61154061/react-and-firebase-routing-issue-blank-screen?noredirect=1#comment108187818_61154061)? – meerkat Apr 11 '20 at 16:06
  • This works.... and don't worry about 'redirect all to your index page', it will actually work with the routes correctly at that point. Worked for me today. – Michael Durrant Dec 06 '20 at 12:53