Android - Invariant failed: Browser history needs a DOM - react-router-dom

I fetch a list of articles from my site backend (nodejs) and print it in the react demo app.
The app works correctly from the Web. When I try to start it in Android I get the following error:
Invariant failed: Browser history needs a DOM
I think the problem is here:
import {BrowserRouter, Router, Link, Route, Switch} from 'react-router-dom';
...
<BrowserRouter>
<Switch>
<Route path="/detail/:id" component={RouterDetail}/>
<Route exact={true} path="/home" render={() => content}/>
</Switch>
</BrowserRouter>
I have read everything on the web about this error but I have not been able to understand the problem.
I found a lot about react server side.
But my case is different, i use react only as a frontend.
I also tried the following change, from web works, on android I encounter the same problem:
import { Router } from "react-router";
import {Link, Switch, Route} from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory';
...
const history = createBrowserHistory();
...
<Router history={history}>
<Route path="/detail/:id" component={RouterDetail}/>
<Route exact={true} path="/home" render={() => props.content}/>
</Router>

Related

Stop statically served React app from calling server path

My app has the default homepage at "/", and a contact page at "/contact". When I ran the react server(localhost:3000) and express server(localhost:8000) separately, the navigation between these pages works fine as handled by "react-router-dom" below.
Frontend React, Routing.tsx:
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Contact from "../pages/Contact/Contact";
import Main from "../pages/Main/Main";
import Error from "../pages/Error/Error";
function Routing() {
return (
<BrowserRouter>
<Switch>
<Route path="/error" component={Error} />
<Route path="/contact" component={Contact} />
<Route path="/" component={Main} />
</Switch>
</BrowserRouter>
);
}
export default Routing;
Now I built the react app using npm run build, and placed the "build" folder inside my backend express server to be served, as per deployment doc here. Then I ran "npm run dev" to start the server.
However, whenever I try to navigate to the /contact page, it issues a server call to "localhost:8000/contact" instead of being handled by the frontend routing. Of course the server doesn't have that route, and all my server routes are prefaced with "/api/" anyway.
How can we prevent frontend navigation from calling the server routes?
More code below, thanks.
Backend Express, App.ts:
import express from "express";
import path from "path";
class App {
private _app: express.Application;
private readonly _port: number | string = process.env.PORT || 8000;
constructor(controllers: any[]) {
this._app = express();
this.initializeControllers(controllers);
this.initializeMiddleWares();
this.initHostingReactUI();
}
public start() {
this._app.listen(this._port, () => {
console.log(`App listening on the port ${this._port}`);
});
}
private initializeControllers(controllers: any[]) {
controllers.forEach((controller) => {
this._app.use("/api", controller.router);
});
}
public initializeMiddleWares() {
require("./src/middleware/express.middleware")(this._app);
}
public initHostingReactUI() {
// I am aware that you can do "/*" below to catch all routes, but that doesn't solve my issue as it still calls the backend for every non-api routes that should be handled by frontend routing.
this._app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "build", "index.html"));
});
}
}
export default App;
Backend Folder structure with Build folder:
If needed:
Backend github source.
Frontend github source
There are two ways to combine the routes between the frontend and backend:
If access from http://localhost:3000
You need to boot both frontend and backend.
In this case, all your backend request urls will start with http://localhost:3000 (if you didn't specify a base url). To solve this issue, add a line in the root of your client-side package.json file:
{
"proxy": "http://localhost:8000"
}
After that, frontend will redirect all the unknown routes to backend.
If access from http://localhost:8000
You only need to boot the backend.
Since React application is one-page application, which means there is only one html entry (index.html). Now we need a route to serve the frontend routes in the backend:
// place this in the end after the other routes
app.get('*', (req, res) =>
res.sendFile(path.join(__dirname, "build", "index.html"));
})
The routing system will check if the route exists among the backend routes. If not, then serve index.html and check if the route exists among the frontend routes. Therefore, in the frontend you should guard the urls by returning a 404 page when not found.
Do you mean navigate through the app? if not, navigating to the page by the URL or refreshing the page always will send a request to the server, which should return the app index.js.
All you need to do is to place the last route which is serving react (You can use app.get('*', .....) or placingapp.use((req, res) => {...}) without route).
In this case, when the request came to the server, the server will search for the route top-to-bottom, if the requested route is not api then it's will serve the client-side app.

React app server wont restart automatically using create react app

I am Making a simple app using create-react-app
but the server stops and won't update with changes
Plz Help
npm version 6.14.4
node version 10.19.0
Ubuntu 20.04 LTS
WSL 2 Windows 10 Home\
My Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
My app.js
import React from 'react';
import Palette from './Palette';
import seedColors from './seedColors'
import './App.css';
function App() {
return (
<div className ="App">
<Palette colors ={seedColors[3]}/>
</div>
);
}
export default App;
My Palette.js
import React, { Component } from "react";
class Palette extends Component{
render(){
return(
<div><h1>Palette</h1></div>
)
}
}
export default Palette
The seedColors.js ,I have taken from https://github.com/Colt/react-colors/blob/master/colors-app/src/seedColors.js
Try adding a .env file to your root project directory (where you have package.json and node_modules). Then inside .env, add CHOKIDAR_USEPOLLING=true. This just worked for me when I was having issues with hot reloading not working. Apparently the "watcher" requires this setting when working with a VM (like WSL). I found this recommended in the top answer here: React create app hot reload is not always working on linux

Why does my React Website Take 43 seconds to Load?

I'm not sure why my react website is taking so long to load. It takes 43 seconds
All I have is in index.jsx
import ReactDOM from "react-dom";
import React from "react";
import { HashRouter, Route } from "react-router-dom";
import Home from "./components/Home";
ReactDOM.render(
<HashRouter>
<div>
<Route exact path="/" component={Home} />
</div>
</HashRouter>,
document.getElementById("main")
);
Home.jsx: imports react and renders hi
webpack.config.js : https://pastebin.com/raw/zdUws0R8
package.json : https://pastebin.com/raw/VR6pSP44
index.html : https://pastebin.com/raw/9AVNBpTN
I checked your website and it seems to be working fine to me for now;
For more details, I have added a:
Website Request screenshot
You might want to have a look at your SSL certificate though.
All the best!
I think you need to reinstall your project via :
npx create-react-app YourProject
and use
BrowserRouter
instead of
HashRouter
in 'react-router-dom'
then start the development server after creating the components or editing it via
npm start

React Router with expressjs and httpd not working

I have deployed my React App on expressjs, I have httpd already setup to redirect all request /MyApp to my application on expressjs.
Once the expressjs server is up I am able to access my application as http://localhost:3000/.
I have Routers in my react app which will route me to the login page on the above call.
When I try to access through httpd as http://localhost/MyApp/, I get a blank page, the component doesn't get rendered.
Assuming that react-router is unable to handle /MyApp/.
How can I achieve this?
app.use, app.get with the route "/MyApp" didn't work.
App.tsx
<Router>
<Route render={({ location, history }) => (
<React.Fragment>
<Suspense fallback={<Loader/>}>
<Switch>
<Route path="/" exact component={Login} />
<Route path="/home" component={LoginSuccess} />
</Switch>
</Suspense>
</React.Fragment>
)}
/>
</Router>
Using BrowserRouter

React.js website build works on one host, but not another

I am new to react.js . I have created a react website using create-rect-app. I have run: npm run build in git and got my static site files. Everything works on the test host, however when i moved hosts only index page works and navigating to other page gives 404 error. For routing im using react-router-dom.
How can i get my page to work on the other host?
Working host: http://000webhost.com/
Badly working host is some local provider
Edit: Basically i have pages such as /Home and /Contact.
Im using react-router-dom.
code:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route} from 'react-router-dom';
import logo from './logo.svg';
import './App.css';
import Home from './pages/Home.jsx';
import Contacts from './pages/Contacts.jsx';
import Our_products from './pages/Our_products.jsx';
class App extends Component {
render() {
return (
<Router>
<div>
<Route exact path ="/" component={Home}/>
<Route exact path ="/Home" component={Home}/>
<Route exact path ="/Contacts" component={Contacts}/>
<Route exact path ="/Our-products" component={Our_products}/>
</div>
</Router>
);
}
}
export default App;
My index is linked to /Home as you can see from code. i have uploaded Build folder to public_html on both hosting platforms. On one site works normaly, on the other only /Home page shows up.
So, you can ignore this, but what helped is changing
<a href="/" />
to
<Link to="/" />
. Basically one hosting provider could render links as
<a />
other only as
<Link />

Resources