React-router: createHistory error when trying to use createBrowerHistory

Created on 7 Oct 2016  路  26Comments  路  Source: ReactTraining/react-router

I have tried substituting createBrowserHistory for createHistory in my basename configuration for a React application and keep getting the error "createHistory is not a function" EVEN THOUGH createHistory is NOT EVEN IN MY CODE. It seems that bundle.js is picking up createHistory from the history module at some point (rather than using createBrowserHistory. Frankly, I am baffled by this, since the createBrowserHistory substitution is something that I picked up from examples and can't see why it shouldn't work.

This happens even when I include both {createBrowserHistory, createHistory} -- which shouldn't be necessary.

I have history v 2.1.0 in the top level of node_modules repository and history v 2.1.0 in the top of my "react-router" module.

const history = useRouterHistory(createBrowserHistory)({
basename: '/react_librivox_search/'
});

TypeError: createHistory is not a function
useBasename/<()bundle.js (line 27095)
useQueries/<()bundle.js (line 24459)
useRouterHistory/<(options=Object { basename="/react_librivox_search/"})

Most helpful comment

Such a mess, I tried 18438889239889455023 different configurations found all over Stack Overflow and GitHub and none seems to work: why can't anybody point out a 2017 working version of "basename in react-router"?

All 26 comments

break on exceptions and see what's going on, happy to reopen if you find a problem but it seems unlikely, wish i had time to help you debug.

The documentation for basename customization is wrong for the current version ( 2.8.1) of react-router that I happen to be using:

https://github.com/ReactTraining/react-router/blob/master/docs/guides/Histories.md


Defining a basename:

import { useRouterHistory } from 'react-router'
import { createHistory } from 'history'

const history = useRouterHistory(createHistory)({
basename: '/base-path'
})


FIRST

"import {createHistory} from 'history'" tries to find the history module in the top-level node_module folder. IF you have the current history (v 4.3.0) installed there, it does NOT have a "createHistory" function. So createHistory is UNDEFINED. When it is injected into useRouterHistory(createHistory), this causes the "createHistory is not a function" error when the code hits the following webpack transpiled code:

function useBasename(createHistory) {
return function () {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var history = createHistory(options); <----- ERROR IS HERE
. . . .

SECOND

react-router (v 2.8.1) now has its OWN included history dependency in "node_modules/history". Presumably THIS is the one that we are supposed to use. To import that, you have to do this:

 import createBrowserHistory from 'react-router/node_modules/history/lib/createHistory';

You might THINK that the following would work (if history has been imported into the react-router package), but it doesn't:

 import createHistory from 'react-router';

It also gives the "createHistory is not a function" error (createHistory is UNDEFINED).

FINALLY

According to Dan Abramov,

"I know it's somewhat confusing鈥攎aybe we should just rename createHistory to something like
createAbstractHistory or whatever just so people stop importing it by mistake. createHashHistory() and
createBrowserHistory() are compatible with React Router, but createHistory() is low-level and isn't meant
for use with it." ( https://github.com/mjackson/history/issues/106 )

So the solution for me was the following, since I in fact wanted to use browserHistory:

 import { useRouterHistory } from 'react-router';
 import { createBrowserHistory } from 'react-router/node_modules/history/lib/createBrowserHistory';

 const history = useRouterHistory(createBrowserHistory)({
      basename: '/base-path'
 })

ReactDOM.render(
    <Provider store={librivoxStore}>
        <Router history={history}>    <--- Then reference history in the router JSX
        . . . . 

EXTRA NOTE:

When I try to include createHistory with

import createHistory from 'react-router/node_modules/history/lib/createHistory'; 

I got the following error:

TypeError: getCurrentLocation is not a function

So Abramov seems to be right, and the documentation is really OFF in showing the use of createHistory with the current version of react router.

Such a mess, I tried 18438889239889455023 different configurations found all over Stack Overflow and GitHub and none seems to work: why can't anybody point out a 2017 working version of "basename in react-router"?

The examples use it

@ryanflorence examples where? I can't even find those with any reference to useRouterHistory

@shawnmclean ... useRouterHistory is no longer in react-router under node_modules

This worked in 3.0.2 but not now in 4.0.0

...
import { useRouterHistory } from 'react-router'
import { createHistory } from 'history'
...
// Set up the router history off the base application name.
const browserHistory = useRouterHistory(createHistory)({ basename: '/sample-app' })
const historyRouterMiddleware = routerMiddleware(browserHistory)

Test app here if you would like to see more - https://github.com/rpoitras/sample-app

Was in the same situation as @damianobarbati (tried countless approaches without success), but finally was able to get rid of the createHistory is not a function error by slightly changing the import 馃槻

- import { createBrowserHistory } from 'react-router/node_modules/history/lib/createBrowserHistory';
+ import createBrowserHistory from 'react-router/node_modules/history/lib/createBrowserHistory';
import { Router, Route, useRouterHistory } from 'react-router';
import createBrowserHistory from 'react-router/node_modules/history/lib/createBrowserHistory';

const browserHistory = useRouterHistory(createBrowserHistory)({
  basename: '/apps/test/myapp/myapp.html',
});

FWIW: here the output from npm ls history

+-- [email protected]
`-- [email protected]
  `-- [email protected]

You need to pair react-router 3.x with history 3.x. You have the wrong version of history installed.

@timdorr thanks for your comment. I'll inform the app devs (I'm only doing the integration into the CMS and have no prior experience with react). Anyway, it seems to work now with the mentioned changes, so I tought it might still be valuable for others that are experiencing the same issue.

Just make sure, if you're using react-router 3.x, you do npm install --save history@3 react-router@3

@timdorr any tips/docs on how to replace useRouterHistory() in [email protected]?
Here are my attempts at react-router 3 -> 4 - https://github.com/rpoitras/sample-app/tree/react-router-4

Sorry about all the spam on a closed issue. I think <Router> will need to be replaced with <BrowserRouter> and then put the basename tag in there. I'm still have problems with syncing the history with the store. I'll keep digging and stop posting on here.

It seems that simply setting the basename in createBrowserHistory like described in the history docs does not work.

const history = createHistory({
  basename: '/the/base'
}) 

@kimasendorf
For react-router 2.4 .. 3.x this works for me:

const browserHistory = useRouterHistory(createHistory)({ basename: '/sample-app' })

For react-router 4.0.0:

const browserHistory = createBrowserHistory()
...
<BrowserRouter basename='/sample-app'>  // from react-router-dom

Full examples:
https://github.com/rpoitras/sample-app
https://github.com/rpoitras/sample-app/tree/react-router-4

@timdorr, I'm seconding @rpoitras' question - are there any tips or docs on how to replace useRouterHistory() in [email protected]?

You don't need to. Just create a history instance from the history library. It works without modification now.

Hi @gabygandrade here is an example of setting up browser history in a store https://github.com/rpoitras/sample-app/blob/react-router-4/src/main/web/app/store.js

And then using it in the app's main entry point https://github.com/rpoitras/sample-app/blob/react-router-4/src/main/web/app/index.js

Hope this helps.

@merges most stuff is in here: https://reacttraining.com/react-router/

Pretty frustrating how poor the docs are on upgrading to v4 re: history. None of the suggested approaches are working, even trying your sample app @rpoitras is giving me errors re: Could not find a declaration file for module 'history/createBrowserHistory' using history@4, react-router@4, react-router-dom@4....

@dwasyluk that example has gotten stale. I'll do some upgrades and make sure it's working. One other thing I want to change is the usage of static routing. I think the authors recommendations are best.

@dwasyluk https://github.com/rpoitras/sample-app/tree/react-router-4 should be working now. I'd suggest starting with a fresh node_modules. BTW I cannot upgrade past [email protected] or HMR stops working properly. When making changes to a React Component I get:

[HMR] Cannot apply update. Need to do a full reload! 
[HMR] Error: Aborted because <some-component> is not accepted Update propagation:

[hmr] (probably because of restarting the server)
[hmr] cannot find update. need to do a full reload!
react [hmr] cannot apply update. need to do a full reload!
the following modules couldn't be hot updated: (they would need a full reload!)

@dwasyluk
Fixed the webpack/HMR issue. I had to remove the routes bundle. Older versions of webpack was able to descend the tree from the main app's index in one bundle to the routes in another bundle. That doesn't seem to work anymore.

I getting the same error as- WEBPACK_IMPORTED_MODULE_10_history_createBrowserHistory__.createHistory is not a function. I have "react": "^15.6.1", "react-router": "^4.1.1", "react-router-dom": "^4.1.1",
"react-router-redux": "^4.0.8". Please help me
I am not getting the solution anywhere.

@sugandhgoyal You have to use react-router-redux@next. The previous version is likely giving you the wrong version of history to import from.

Not to pile on the mixed messages in this thread, but i went back and forth trying to get rid of my warnings about using base in my index.html header. This post seemed to be exactly the same thing I was experiencing. I ended up removing React-Router (v2.x) and History (vX.x) from my project and reinstalling using version 3 for React-Router.

npm install --save react-router@3

I didn't not explicitly include v3.x history install as I hoped react-router's install would install what it needed, which it appeared it did.

I did not have to do any workarounds using createBrowserHistory at this point. Simply using:

import { useRouterHistory } from 'react-router'
import { createHistory } from 'history'

const history = useRouterHistory(createHistory)({
basename: '/base-path'
})

ReactDOM.render(
  <Router history={history}>
....

Worked fine at that point. I didn't even realize the relationship between react router in history. For the record, I did try the same with version React Router 4.x but got error

TypeError: (0 , _reactRouter.useRouterHistory) is not a function

So dropped down to 3.x and thats when everything worked. Good luck to any with this issue.

Just replace:
import { createHistory } from 'history'
to:
import createHistory from 'history/createBrowserHistory'

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hgezim picture hgezim  路  3Comments

alexyaseen picture alexyaseen  路  3Comments

davetgreen picture davetgreen  路  3Comments

jzimmek picture jzimmek  路  3Comments

maier-stefan picture maier-stefan  路  3Comments