I'm configuring react-boilerplate to start a project on it.
Our dev environment publishes "dev" versions of the app in sub paths, for example: example.org/test/project-name
Then, when we publish the project, it stays on example.org/
I'd like to use the browser history (HTML5 API) and not the hash history. But this means that I have to set the basename of React Router to match the current environment.
Right now, I'm trying to set up a static basename in this way:
const browserHistory = useRouterHistory(useBasename(createHistory))({
basename: '/test/project-name',
});
const store = configureStore(initialState, browserHistory);
But when I run the application, the homepage is still at / instead of /test/project-name/.
So, the questions are:
What am I doing wrong?
How would you make the basename match the current environment?
The answer is in the react-router documentation:
Be aware that useRouterHistory already pre-enhances your history factory with the useQueries and useBasename enhancers from history.
import { useRouterHistory } from 'react-router'
import { createHistory } from 'history'
const history = useRouterHistory(createHistory)({
basename: '/base-path'
})
Related
Is it possible to create a global history file to manage the createBrowserHistory() on react-router-dom v5?
I know the V5 has the useHistory() as a way to get the history. But is it possible to retrieve the history from anywhere, like for cases where I am not using a function component?
On V4 I could create a file history.js:
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
It works on V4
https://codesandbox.io/s/react-router-v4-nfwr0
It doesn't work on V5 - It updates the URL but redirects to not-found
https://codesandbox.io/s/react-router-v5-not-working-jlrep
As the doc says you should use the v4 of history to work on react-router v5.
https://github.com/ReactTraining/history
Documentation for version 4 can be found on the v4 branch. Version 4 is used in React Router versions 4 and 5.
I solved this by doing this.See what i done
Create a file like before
This is the code
import {createBrowserHistory} from 'history';
import store from 'store';
export default createBrowserHistory({
basename: store ? store.getState().productionBaseUrl : ''
});
The reason why i import Redux is the project does not pulish on nginx root folder.So i should add a basename.If you do not neet it,you can remove it.
Then you can use it in your own coponnet. How to use? Let me show your the code.
// if my history in src/router/
import history from 'router/history';
history.push(`${your router address}`)
Attention
The history's push method can pass an object like the origin props.But it's refresh when in the child router always. So pass a string when use it.
is possible to implement relative paths on https://name.github.io/project in React for gh-pages, using React Router, as I receive errors.
I used import {withRouter} from 'react-router-dom'; and export default withRouter(componentName); to forward routing props from Router to targeting component, and I receive them.
I tried implemented like this Links:
<li><Link to={{pathname: this.props.match.url + '/new-post'}}>New Post</Link></li>
and used this modality this.props.match.url to obtain current path, but I receive errors.
Has anybody some suggestions?
It can be configured in react router history:
history.js
import createBrowserHistory from 'history/createBrowserHistory';
const history = createBrowserHistory({
basename: 'project',
});
export default history;
Is there any way to create an action in your MobX store, which pushes your app to a new url using react router v4, e.g. this.props.history.push...
I constantly get a history undefined error, but am unsure how to access the history from my store.
The history push called from the component itself does work though..
many thanks! (this is driving me crazy..)
Since I stumbled across the same issue, I'll share my solution. I just put the RouterStore into its own file in my stores directory, then if I needed access to history or location or whatever, I would import the routing store into the store I was currently working in.
./stores/routing.ts
import { RouterStore } from 'mobx-react-router'
export default new RouterStore()
./stores/other-store.ts
import routing from './routing'
export class OtherStore {
#action
doSomething = () => {
routing.push('/new-route')
}
}
export default new OtherStore()
./index.ts
import { Router } from 'react-router-dom'
import { Provider } from 'mobx-react'
import createBrowserHistory from 'history/createBrowserHistory'
import { syncHistoryWithStore } from 'mobx-react-router'
import otherStore from './stores/other-store'
import routing from './stores/routing'
const browserHistory = createBrowserHistory()
const stores = {
otherStore,
routing,
}
const history = syncHistoryWithStore(browserHistory, routing)
ReactDOM.render(
<Provider {...stores}>
<Router history={history}>
<App />
</Router>
</Provider>,
document.getElementById('root'),
)
You can use mobx-react-router to put react-router in a mobx store and then use it by injecting it in components.
You can also pass the router store as a constructor argument to your other stores that need it. This way you have the router history instance available in your mobx store.
I would like to add a simpler solution that does not require any additional libraries. React Router version is 5.2
Among my stores i've created a HistoryStore.js with the following code:
import { createBrowserHistory } from 'history';
export class HistoryStore {
history = createBrowserHistory();
}
Then I create an instance of it in my contexts.js file but you could do it right away.
export const history = new HistoryStore();
After that you import it in your index.js and pass it as a history prop to the Router.
That's it. Now you could import this store into any other and use it there. When you use useHistory hook in your component it gets this history object, so your history in synchronized.
I have an uncontrolled link tag <a class="link" href="#">Click Me</a> I wish to use to invoke a route change in react.
// Slowly shifting from JQuery
$(".link").on("click", (evt) => {
evt.preventDefault();
var browserHistory = createBrowserHistory();
browserHistory.push('/detail/' + evt.target.dataset.id);
// expect react-router to update view based on route change
// ???
});
I would like to eliminate a full page reload if at all possible. Therefore, calling location.href="/detail/" or anything of similar nature I would like to avoid.
Does anyone know how do I accomplish this?
I found the solution (for me anyway). This turned out to be an issue with the way I was importing the history module into my app.
For reasons I'm not fully able to explain, creating a single history module to be referenced by the other modules in my application resolved this problem.
// history.ts
import createHistory from 'history/createBrowserHistory';
export default createHistory();
Apparently, when importing the history object across other modules, it doesn't reference the same object across these modules; or I was referencing it incorrectly. Each module was referencing a separate history object. This prevented the history.listen(...) (in one module) from detecting the history.push(...) in another module.
// app.tsx
/* FAILS: Creates multiple history objects across modules */
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
/* SUCCEEDS: This creates a single history object shared across modules */
import history from './history'; // This works!
...
ReactDOM.render(
<Router history={history}>
<App.Frame>
...
</App.Frame>
</Router>
, document.getElementById('root')
);
// config.ts
/* FAILS: Creates multiple history objects across modules */
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
/* SUCCEEDS: This creates a single history object shared across modules */
import history from './history'; // This works!
...
$('.link').each((i, e) => {
$(e).on("click", (evt) => {
evt.preventDefault();
history.push('/detail/' + evt.target.dataset.id);
});
})
Credit to the following post that led me to the solution: Routing in React, the uncomplicated way
I've updated react-router to the latest version - 2.4.1
I use hashHistory in my app
import { Router, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
// useRouterHistory creates a composable higher-order function
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false })
<Router history={appHistory}/>
And now I'm getting an error
Warning: Using { queryKey: false } no longer works.
Instead, just don't use location state if you don't want a key in your URL query string
How can I fix this?
I don't want additional query key to appear in url. I expect the same behaviour as from angular router or backbone router.
This warning does not actually originate from React Router but the history module it uses. In fact, the latest version (3.0.0, May 30 2016) doesn’t work at all with React Router:
Uncaught Invariant Violation: You have provided a history object created with history v3.x. This version of React Router is not compatible with v3 history objects. Please use history v2.x instead.
This warning is present as of v2.5.1 (Jun 24 2016).
So the easiest solution is to just use the same version React Router uses, courtesy of its package.json:
"history": "^2.0.1"
After that, the queryKey option works as expected.
You can use const history = useRouterHistory(createHashHistory)(); but then the refresh or back button will result in white page. It works very similar to browserHistory which requires mod_rewrite or middleware to function properly.
Maybe someone knows why they changed it like this because for me it doesn't make sense.
This worked for me
const appHistory = useRouterHistory(createHashHistory)();