Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make react router work with static assets, html5 mode, history API and nested routes?

I thought I was starting to understand React Router, but I hit a new wall when adding a library that loads css for its components. Everything works fine when a navigate from my home, to the page containing the component, but when I refresh it, the urls of the fonts are broken...

I found some pointer here and here but no luck so far. Is this a common issue ? How to work around it ?

I use webpack dev server with default config built by a yeoman scaffolder.

The library I use is React Fa to display icons.

When I load my app on http://localhost:8000/ everything displays fine, then I navigate to http://localhost:8000/customer/ABCD1234/chat and my icons are ok. The font was loaded properly.

Then I refresh the page, and I see in the console :

DOMLazyTree.js?019b:56 GET http://localhost:8000/customer/ABCD1234/assets/926c93d201fe51c8f351e858468980c3.woff2

Which is obviously broken because the customer part shouldnt be here...

Here is my router so far :

ReactDOM.render(   <Router history={browserHistory}>     <Route path='/' component={App}>       <IndexRoute component={Index}/>       <Route path='customer/:id'        component={Customer}    />       <Route path='customer/:id/chat'   component={CustomerChat}/>       <Route path="*"                   component={ NotFound }  />     </Route>   </Router> , document.getElementById('support-app')); 

I also tried adding a <base href="/"/> to my index.html, but I get a nice warning in red in the console, so maybe not the best idea :

Warning: Automatically setting basename using is deprecated and will be removed in the next major release. The semantics of are subtly different from basename. Please pass the basename explicitly in the options to createHistory

like image 578
Sephy Avatar asked Apr 28 '16 18:04

Sephy


People also ask

How do I use nested routes in react router?

Nested Routes in React Router We will continue working on the User component, because this is the place where we want to have the nested routing via tabs. Therefore, we will instantiate a new set of Link components (which will be our unstyled tabs) which navigate a user to their profile and their account.

Does react router use history API?

React Router uses the history package, which builds on the browser history API to provide an interface to which we can use easily in React apps. location - (object) The current location. May have the following properties: pathname - (string) The path of the URL.

Can we use nested routes in react?

js application to implement nested routing in the current version of react-router that is React Router DOM version 6. We use nested routing in our application so that a parent component has control over its child component at the route level.

How do I push to history on my react router?

Using history.push() is another approach where we make use of the history props React Router provides while rendering a component. In other words, this works when the component is being rendered by React Router, bypassing the component as a Component prop to a Route.


2 Answers

It sounds like you have defined relative paths to your assets and icons in your CSS.

background-image: url('assets/image/myicon.png')

instead, try an absolute path:

background-image: url('/assets/image/myicon.png')

As React apps are single page applications, and you enter your app on /, all urls are going to work fine no matter the page you navigate to, since they are relative to the root where you started.

But as soon as you reload your page on a different path such as /customer/ABCD all your assets are going to be relative to that, hence the wrong url you see in your console.

Also, if using webpack, you can try to set your publicPath in your config file like this:

... output: {     path: 'assets',     publicPath: '/' }, ... 
like image 118
hampusohlsson Avatar answered Oct 05 '22 23:10

hampusohlsson


I hava a same problem.

  1. Add a <base href="http://whatever"> tag to the head of a page containing react-router's HTML using the default browserHistory

  2. Load the page - history.js will output 2 errors, Warning: Automatically setting basename using <base href> is deprecated and will be removed in the next major release. The semantics of are subtly different from basename. Please pass the basename explicitly in the options to createHistory

  3. Change the react-router history to use history where history is const history = useRouterHistory(createHistory)({ basename: 'http://whatever' }), which should fix the problem (as basename is now explicitly passed)

  4. Reload the page

https://github.com/reactjs/react-router/issues/3387

5/9 update

In my case.

index.html

<head>   <base href="/" />   <script src="app.js"></script> </head> <body>   <div id="app">   </div> </body> 

app.js

import { Router , useRouterHistory } from 'react-router' import { createHistory } from 'history'  const browserHistory = useRouterHistory(createHistory)({ basename: '/' })  render(   <Router routes={routes} history={browserHistory}/>,   document.getElementById("app") ); 

And then reload the warning to disappears. hope this is useful.

like image 31
RoyLiou Avatar answered Oct 06 '22 00:10

RoyLiou