Upgrading React-Router and replacing hashHistory with browserHistory - reactjs

I have a bootstrap+react theme that was using react-router 1.x and hashHistory and I wanted to remove the hash so followed this advice.
Initially I tried to do this while having the 1.x version and I was unable to do it so I've decided to upgrade react-router to 2.x.
After installing react-router 2.x the app worked because it was still using hashHistory but when I replaced it with browserHistory:
it showed a grey screen
the HTML of the app had only the <noscript data-reactid=".0"></noscript> tag inside it
the React Developer Tools showed me that the router had a null inside it
I also checked the Network tab and all files were downloaded properly, and had the right content
surprisingly the was nothing printed in the JavaScript Console, no error/no warnging (I'm really shocked about this, but I'm new React, I would like to know what to do in situations like this).
Here are my changes to Router.jsx:
import React from 'react'
import {render} from 'react-dom'
-import {Router} from 'react-router'
+// import {Router} from 'react-router'
+import { Router, Route, Link, browserHistory } from 'react-router'
+// import { useRouterHistory } from 'react-router'
+// import { createHashHistory } from 'history'
+// import { createBrowserHistory } from 'history'`
import History from '../components/layout/navigation/classes/History.js';
import Routes from './Routes.jsx';
+// const appHistory = useRouterHistory(createHashHistory)({ queryKey: false })
+
var rootInstance = render((
- <Router history={History}>
+ <Router history={browserHistory}>
{Routes}
</Router>
), document.getElementById('smartadmin-root'));`
The backend uses the Phoenix Framework.
Later Edit:
Here you have the hashHistory version that works
https://gitlab.com/blockbuster/react-router-2-with-hash-working/tree/master
And here is the browserHistory version that doesn't:
https://gitlab.com/blockbuster/react-router-2-with-browserHistory-not-working/tree/master
The react code for both can be found under the src directory.
To run the app you need to have Elixir, Phoenix and Postgresql installed, to get backend dependencies( run $ mix deps.get), get frontend dependecies( npm install and bower install), to change the database username and password in config/dev.exs, to create and migrate the database mix ecto.create && mix ecto.migrate and finally run mix phoenix.server.

Have you tried it this way in your Router.jsx?
import React from 'react'
import {render} from 'react-dom'
import { Router, Route, Link, browserHistory, useRouterHistory } from 'react-router'
import createBrowserHistory from 'history/lib/createBrowserHistory'
import History from '../components/layout/navigation/classes/History.js';
import Routes from './Routes.jsx';
const appHistory = useRouterHistory(createBrowserHistory)({ queryKey: false })
var rootInstance = render((
<Router history={appHistory}>
{Routes}
</Router>
), document.getElementById('smartadmin-root'));

Since there is no solution yet, find my (minimalistic) router version below, that is working for me.
Dependencies:
react#15.1.0
react-dom#15.1.0
react-router#2.4.0
History.js is not needed explicitly, since it is a dependency of react-router.
Webpack
Make sure to add
devServer: {
historyApiFallback: true
}
to your webpack.config.js, since webpack-dev-server might have some issues routing correctly (mostly in terms of backwards navigation).
import React from 'react';
import {render} from 'react-dom';
import {Router, Route, IndexRoute, browserHistory} from 'react-router';
import {Routes} from './Routes'; // your routes file
render(
<Router history={browserHistory}>
{Routes}
</Router>,
document.querySelector('#smartadmin-root')
);
I would encourage you to try this code and leave out your hotloading stuff.
Let me know if it helps and if there are any questions. I'm glad to edit my post as needed.

Related

Error message with: Web3 + create-react-app + webpack 5

I am writing the frontend for a Dapp.
I have the script /src/config/index.js
import Web3 from 'web3';
const getLibrary = (provider) => {
return new Web3(provider);
};
export { getLibrary };
And the /src/index.js where I am trying to import getLibrary:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { HashRouter } from 'react-router-dom';
import { ChakraProvider } from '#chakra-ui/react';
import { Web3ReactProvider } from '#web3-react/core';
import { getLibrary } from './config/web3';
ReactDOM.render(
<React.StrictMode>
<HashRouter>
<ChakraProvider>
<Web3ReactProvider getLibrary={getLibrary}>
<App />
</Web3ReactProvider>
</ChakraProvider>
</HashRouter>
</React.StrictMode>,
document.getElementById('root')
);
But, I have the error
The line responsible for the error is:
import { getLibrary } from './config/web3';
I used create-react-app to build the project.
I have try several ideas but nothing is working for me... any help, please?
I had the same problem when using web3 with react and webpack 5. This helped me solve it. I followed option #1 as I couldn't get the other option to work (my main confusion being where to keep webpack.config.js since I had kept it at the root and it was not being picked up).
For anyone looking to resolve this still (2022-08-30), I recommend reading this article:
https://alchemy.com/blog/how-to-polyfill-node-core-modules-in-webpack-5
It will be different in regards to your dependencies but it helped resolve my issues. It basically adds support back in by rerouting requests to dependencies using the react-app-rewired package.

Attempted import error: 'useRouteMatch' is not exported from 'react-router-dom'

I have this error when I try to import useRouteMatch from react-router-dom module, I have this error :
Attempted import error: 'useRouteMatch' is not exported from
'react-router-dom'.
do I have a wrong version of the react-router-dom module ?
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useRouteMatch,
useParams
} from "react-router-dom";
I looked in the module's exports, and in fact, it's not exported. Do I have a wrong version of it ?
import _BrowserRouter from "./BrowserRouter";
export { _BrowserRouter as BrowserRouter };
import _HashRouter from "./HashRouter";
export { _HashRouter as HashRouter };
import _Link from "./Link";
export { _Link as Link };
import _MemoryRouter from "./MemoryRouter";
export { _MemoryRouter as MemoryRouter };
import _NavLink from "./NavLink";
export { _NavLink as NavLink };
import _Prompt from "./Prompt";
export { _Prompt as Prompt };
import _Redirect from "./Redirect";
export { _Redirect as Redirect };
import _Route from "./Route";
export { _Route as Route };
import _Router from "./Router";
export { _Router as Router };
import _StaticRouter from "./StaticRouter";
export { _StaticRouter as StaticRouter };
import _Switch from "./Switch";
export { _Switch as Switch };
import _generatePath from "./generatePath";
export { _generatePath as generatePath };
import _matchPath from "./matchPath";
export { _matchPath as matchPath };
import _withRouter from "./withRouter";
export { _withRouter as withRouter };
Please help, I need your brain :)
If upgrading from v5 to v6, replace useRouteMatch with useMatch per the upgrade guide...
https://reactrouter.com/docs/en/v6/upgrading/v5#replace-useroutematch-with-usematch
I had the same issue, for me I just needed to update the version of react-router I was using.
useRouteMatch was added with react-router V5.1 https://reacttraining.com/blog/react-router-v5-1/#useroutematch
Update your package.json to "react-router-dom": "^5.1.2",
Delete node modules and run npm install
Simply update your react-router-dom version to latest.
npm i react-router-dom#latest
I Solved updating react-router-dom to a version greater than 5.1
npm install react-router-dom#5.1.2 --save
Dont forget to boot the app again with npm start to see the changes.
Check react-router-dom version should be compatible or greater than "5.1" so you can use some hooks like useRouteMatch(), useHistory()..
For anyone who finds this thread because they are attempting to implement 'useRouteMatch' to nest routes in child components, the short answer is that React Router has made updates in v 6.6.0 that are worth getting the scoop on.
Read Here: https://reactrouter.com/en/6.6.0/upgrading/v5#relative-routes-and-links
The Route Path is now relative meaning that it is automatically implied in your route code in your child component:
import React from 'react';
import { BrowserRouter, Link, Route, Routes } from 'react-router-dom';
function App() {
return (
<div>
<h1>Marine Mammals</h1>
<BrowserRouter>
<Routes>
<Route path='/whale/*' element={<Whale />} />
</Routes>
</BrowserRouter>
</div>
);
}
function Whale() {
return (
<>
<h2>Whale</h2>
<Routes>
<Route path='beluga' element={<Beluga />} />
<Route path='blue' element={<Blue />} />
</Routes>
</>
);
}
In App(), an asterisk is added in the path for whale like so: "whale/*".
In Whale(), we no longer need to add anything other than what would replace the '*' like so: path='blue'
The source code comes from a tutorial by DigitalOcean (it's a good tutorial but outdated): https://www.digitalocean.com/community/tutorials/how-to-handle-routing-in-react-apps-with-react-router
Hooks cannot be used inside of a class component. You should refactor your code to be functional. Using the useState and useEffect hooks, you are still able to take advantage of component level state and component lifecycle.
Without the full code from that component I can't do this with your example.

#withRouter Unexpected Token Error

Seems every time I have to setup React Router in a new project I run into something new possibly by version changes.
I am using reactjs and mobx state tree(though at this point have not used anything of it).
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import HomeComponent from './HomeComponent.js';
import {withRouter, Route} from 'react-router'
#withRouter
export default class App extends Component {
render() {
return (
<Route exact path='/' component={HomeComponent}/>
);
}
}
export default App;
When I run it I get
ERROR in ./src/components/App.js
Module build failed: SyntaxError /components/App.js: Unexpected token (6:0)
I also get some warning as well
Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.
Edit
Per the comment from "Artem Mirchenko"
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'mobx-react';
import { useStrict } from 'mobx';
import createBrowserHistory from 'history/createBrowserHistory';
import {syncHistoryWithStore } from 'mobx-react-router';
import { Router } from 'react-router'
import AppContainer from './components/App';
const browserHistory = createBrowserHistory();
import stores from '../src/stores/Stores';
const history = syncHistoryWithStore(browserHistory, stores.routingStore);
ReactDOM.render(
<Provider {... stores}>
<Router history={history}>
<AppContainer />
</Router>
</Provider>,
document.getElementById('app')
);
import {RouterStore} from 'mobx-react-router';
const routingStore = new RouterStore();
const stores = {
routingStore
}
export default stores;
You need to install babel plugin transform-decorators-legacy.
Via yarn:
yard add --dev transform-decorators-legacy
Vie npm:
npm install --save-dev transform-decorators-legacy
And add in to plugins ket in you babel options:
{
// pressets ....
"plugins": ["transform-decorators-legacy"]
}

'react-router' does not contain an export named 'BrowserRouter'

I'm using react-router version 5.5.1 and am trying to use it in my index.js file:
./src/index.js
14:8-21 'react-router' does not contain an export named 'BrowserRouter'
The import statement within my index.js:
import { render } from 'react-dom';
import { BrowserRouter, Match, Miss } from 'react-router';
you need to import BrowserRouter from react-router-dom
import { BrowserRouter } from 'react-router-dom'
more info about BrowserRouter
BrowserRouter is a part of react-router-dom so you've to import it from react-router-dom.
import { BrowserRouter } from 'react-router-dom'
Match and Miss were components in alpha release of react-router. Match has been changed to Route and Miss has been removed. You can use Switch instead of Miss
Refer to this question about Match and Miss
BrowserRouter is in react-router-dom as others have stated. V4 is very different from v3. I recommend looking at their guide to see how to use it. And any examples you look for should be for version 4.
https://reacttraining.com/react-router/web
import { BrowserRouter as Router, Route } from 'react-router-dom'
Issue:
'Route' is not exported from 'react-router-dom' (imported as 'Router').
Solution:
Just close the localhost and Re-run the npm start, its works fine
So I had same issue with Link from react-router-dom. I resolved it by installing same version of react-route and react-router-dom. Looks like react-router-dom doesn't have Link in it.
yarn add react-router react-router-dom
There was an error in your import. BrowserRouter is a part of react-router-dom. so you've to import it from react-router-dom.
import { BrowserRouter } from 'react-router-dom'

How to configure a basename in React Router 3.x

I have an app running at a nested url as opposed to the root. Lets say example.com/app.
I read here that in react router 2.x you could configure basenames.
How can this be done in react router 3.x?
FYI I am also using the react-router-redux package.
This functionality does not exist in React Router anymore. I went through a similar problem and found this fix.
Step 1: Install History (3.0.0)
npm install --save history#3.0.0
Step 2: Import { useBasename } from history in your router file (the file with <Router>):
import { useBasename } from 'history'
Step 3: Modify your <Router> like the below example:
<Router history={ useBasename(() => browserHistory)({ basename: '/app' }) }>
I think the section on configuring histories in the React Router docs is what you're looking for:
https://github.com/ReactTraining/react-router/blob/v3/docs/guides/Histories.md#customize-your-history-further
Here's a full example integrating with react-router-redux (with some unnecessary info excluded):
import React from 'react';
import ReactDOM from 'react-dom';
import createBrowserHistory from 'history/lib/createBrowserHistory';
import { useRouterHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import Root from './containers/Root';
import configureStore from './store/configureStore';
const historyConfig = { basename: '/some-basename' };
const browserHistory = useRouterHistory(createBrowserHistory)(historyConfig);
const store = configureStore({ initialState, browserHistory });
const history = syncHistoryWithStore(browserHistory, store, {
selectLocationState: (state) => state.router,
});
ReactDOM.render(
<Root history={history} store={store} />,
document.getElementById('root')
);

Resources