I have a little problem with my application developed in ReactJS.
Here are my components App.js, AppFront.js and index.js.
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import './index.scss';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>,
document.getElementById('root')
);
serviceWorker.unregister();
App.js
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import AppFront from './AppFront';
import WizardList from './wizard/WizardList';
import './App.scss';
function App() {
return (
<div className="App">
<Switch>
<Route exact path="/" component={AppFront} />
<Route path="/wizard/:id" component={WizardList} />
</Switch>
</div>
);
}
export default App;
AppFront.js
import React from 'react';
import Wizard from './wizard/Wizard';
function AppFront() {
return (
<div className="AppFront">
<Wizard />
</div>
);
}
export default AppFront;
In the application, I have a "Wizard" folder in which are included the components "dataWizard.js", "Wizard.jsx" and "WizardList.jsx"
folder-structure
The "dataWizard.js" file contains an array of objects.
export const dataWizard = [
{
id: "1",
name: "Harry Potter",
category: "Gryffondor",
text: "Harry is a powerful wizard."
},
{
id: "2",
name: "Drago Malefoy",
category: "Serpentard",
text: "Draco Malfoy is not very brave."
}
The "Wizard.jsx" component loops on this table and transmits the properties with the component of "react-router-dom".
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { dataWizard } from './dataWizard';
import './style/Wizard.scss';
class Wizard extends Component {
render() {
return (
<div className="Wizard">
{
dataWizard.map((wizard, i) =>
<Link
to={{ pathname: `/wizard/${wizard.id}`, state: { wizard } }}
key={i}
>
<span className="name">{wizard.name}</span>
<span className="category">{wizard.category}</span>
</Link>
)
}
</div>
);
}
}
export default Wizard;
I recover the properties without problem with the component "WizardList.jsx".
import React, { Component } from 'react';
import './style/WizardList.scss';
class Wizard extends Component {
render() {
const wizard = this.props.location.state.wizard;
return (
<div className="WizardList">
<div className="container">
<span className="name">{wizard.name}</span>
<span className="category">{wizard.category}</span>
<span className="text">{wizard.text}</span>
</div>
</div>
);
}
}
export default Wizard;
Only when I reload the page, or try to access it directly by typing the path in the URL bar, an error message appears and this.props.location.state is undefined.
Here are some pictures in progressive order to help you better understand my problem.
Homepage - number 1
Information about sorcerer after click - number 2
I am trying to go directly to the informative page on the sorcerer. - number 3
Error message - number 4
Please, I am a beginner, and I have tried several methods seen on the web, but I still cannot resolve this problem. Please, help-me! :)
WizardList gets the data to load from the location.state you are sending it in this Link
<Link
to={{ pathname: `/wizard/${wizard.id}`, state: { wizard } }}
key={i}
>
...but if you refresh in /wizard/:id you have nothing in location.state because you have not followed a link.
However, you have the id of the wizard in the link so you can access it with this.props.match.params.id. Then if there's something in location.state you can use it to load the page but if not, you can take the wizard id and find the proper wizard of the list.
import React, { Component } from 'react';
import { dataWizard } from './dataWizard';
import './style/WizardList.scss';
class Wizard extends Component {
render() {
const wizard = this.props.location ? this.props.location.state.wizard : dataWizard.find(wizard => wizard.id === this.props.match.params.id);
return (
<div className="WizardList">
<div className="container">
<span className="name">{wizard.name}</span>
<span className="category">{wizard.category}</span>
<span className="text">{wizard.text}</span>
</div>
</div>
);
}
}
export default Wizard;
I'm trying to build a simple example project where the user is redirected to the 'contact' page upon clicking a button, using React. I'm trying to achieve this by setting the value of a state property. When I run the code I have, it does change the browser address bar URL to that of the contact page, but does not seem to actually load the component - I get a blank page instead. If I manually navigate to that URL (http://localhost:3000/contact) I can see the contents.
Here are my App.js and Contact.js files -
App.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route, Link, Redirect } from 'react-router-dom';
import Contact from './Contact';
class App extends Component {
state = {
redirect: false
}
setRedirect = () => {
this.setState({
redirect: true
})
}
renderRedirect = () => {
if (this.state.redirect) {
return <Redirect to='/contact' />
}
}
render() {
return (
<Router>
<Switch>
<Route exact path='/contact' component={Contact} />
</Switch>
<div>
{this.renderRedirect()}
<button onClick={this.setRedirect}>Redirect</button>
</div>
</Router>
)
}
}
export default App;
Contact.js
import React, { Component } from 'react';
class Contact extends Component {
render() {
return (
<div>
<h2>Contact Me</h2>
<input type="text"></input>
</div>
);
}
}
export default Contact;
Using state isn't really a requirement for me, so other (preferably simpler) methods of redirection would be appreciated too.
Since your button is nothing more than a link, you could replace it with:
<Link to="/contact">Redirect</Link>
There are many alternatives though, you could for example look into BrowserRouter's browserHistory:
import { browserHistory } from 'react-router'
browserHistory.push("/contact")
Or perhaps this.props.history.push("/contact").
There are pros and cons to every method, you'll have to look into each and see which you prefer.
I got here for a similiar situation. It's possible use withRouter (https://reactrouter.com/web/api/withRouter) to handle that.
This example was tested with "react": "^16.13.1","react-router-dom": "^5.2.0" and "history": "^5.0.0" into "dependecies" sections in package.json file.
In App.js I have the BrowserRouter (usually people import BrowserRouter as Router, I prefer work with original names) with Home and Contact.
App.js
import React, { Component } from "react";
import {
BrowserRouter,
Switch,
Route,
} from "react-router-dom";
import Home from "./pages/Home";
import Contact from "./pages/Contact";
class App extends Component
{
// stuff...
render()
{
return (
<BrowserRouter>
<Switch>
<Route path="/contact">
<Contact />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</BrowserRouter>
);
}
}
export default App;
ASIDE 1: The Route with path="/contact" is placed before path="/" because Switch render the first match, so put Home at the end. If you have path="/something" and path="/something/:id" place the more specific route (with /:id in this case) before. (https://reactrouter.com/web/api/Switch)
ASIDE 2: I'm using class component but I believe (I didn't test it) a functional component will also work.
In Home.js and Contact.js I use withRouter associated with export keyword. This makes Home and Contact components receive the history object of BrowserRouter via props. Use method push() to add "/contact" and "/" to the history stack. (https://reactrouter.com/web/api/history).
Home.js
import React from "react";
import {
withRouter
} from "react-router-dom";
export const Home = ( props ) =>
{
return (
<div>
Home!
<button
onClick={ () => props.history.push( "/contact" ) }
>
Get in Touch
<button>
</div>
);
}
export default withRouter( Home );
Contact.js
import React from "react";
import {
withRouter
} from "react-router-dom";
export const Contact = ( props ) =>
{
return (
<div>
Contact!
<button
onClick={ () => props.history.push( "/" ) }
>
Go Home
<button>
</div>
);
}
export default withRouter( Contact );
Particularly, I'm using also in a BackButton component with goBack() to navigate backwards:
BackButton.js
import React from "react";
import {
withRouter
} from "react-router-dom";
export const BackButton = ( props ) =>
{
return (
<button
onClick={ () => props.history.goBack() }
>
Go back
<button>
);
}
export default withRouter( BackButton );
So I could modify the Contact to:
Contact.js (with BackButton)
import React from "react";
import BackButton from "../components/BackButton";
export const Contact = ( props ) =>
{
return (
<div>
Contact!
<BackButton />
</div>
);
}
export default Contact; // now I'm not using history in this file.
// the navigation responsability is inside BackButton component.
Above was the best solution for me. Other possible solutions are:
useHistory Hook (https://reactrouter.com/web/api/Hooks)
work with Router instead BrowserRouter - (https://reactrouter.com/web/api/Router)
First off, I have read through just about every example I can find and looked through various boilerplates to see how others have done this. I am having issues loading pages when clicking <Link>'s with react-router v4. I have also installed the package react-router-connected and have been trying that out as well but no improvement can be seen (however it shows the changes in the redux-logger which is nice).
Currently, the url updates just fine and if I manually change the url and press enter, then the next page will load. But, it will not redirect if I click a link. I am also using create-react app for the project, just for your reference. My actual app is setup as the exact example from usage with react-router in the official redux docs. For simplicity, I have changed my routes to only include links to basic components that do nothing but redirect to one another.
Root.js which houses my routes
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router'
// import App from './App';
import NewComponent from './NewComponent';
import OldComponentent from './OldComponent';
const Root = ({ store, history }) => (
<Provider store={store}>
<ConnectedRouter history={history}>
<Router>
<Switch>
<Route exact path='/' component={OldComponentent}/>
<Route path='/new' component={NewComponent}/>
{/* <Route path='/' component={App}/>
<Route path='/:filter' component={App}/> */}
</Switch>
</Router>
</ConnectedRouter>
</Provider>
)
export default Root;
Home component
import React from 'react';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
import { withRouter } from 'react-router';
import { Link } from 'react-router-dom';
import Button from 'material-ui/Button';
class OldComponent extends React.Component {
redirectPage = () => { this.props.dispatch(push('/new')); };
redirectPage1 = () => { this.props.dispatch(push('/')); };
render() {
return (
<div>
OLD COMPONENT
<Button onClick={this.redirectPage}>Redirect new</Button>
<Button onClick={this.redirectPage1}>Redirect /</Button>
<Link to='/new'>Redirect Link</Link>
</div>
)
}
}
export default withRouter(connect()(OldComponent));
Other basic component for redirection purposes
import React from 'react';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
import { withRouter } from 'react-router';
import { Link } from 'react-router-dom';
import Button from 'material-ui/Button';
class NewComponent extends React.Component {
redirectPage = () => { this.props.dispatch(push('/')); };
redirectPage1 = () => { this.props.dispatch(push('/new')); };
render() {
return (
<div>
NEW COMPONENT
<Button onClick={this.redirectPage}>Redirect /</Button>
<Button onClick={this.redirectPage1}>Redirect new</Button>
<Link to='/new'>Redirect Link</Link>
</div>
)
}
}
export default withRouter(connect()(NewComponent));
As you can see, they are essentially the same component with minor differences. The url will change to /new or / and will also update the pathname found in the ##router/LOCATION-CHANGE state objects created by react-router-connected package. The url will also change by clicking the <Link> tag but with no redirect.
Any help on how to approach this would be greatly appreciated.
The comment posted by #Supertopoz works this.props.history.push('/pathname') works. However, after setting that up, the <Link> now works as well. I am also using withRouter (which I was before) throughout, so that was another important factor in egtting it to work.
Can anyone please tell me how I can go back to the previous page rather than a specific route?
When using this code:
var BackButton = React.createClass({
mixins: [Router.Navigation],
render: function() {
return (
<button
className="button icon-left"
onClick={this.navigateBack}>
Back
</button>
);
},
navigateBack: function(){
this.goBack();
}
});
Get this error, goBack() was ignored because there is no router history
Here are my routes:
// Routing Components
Route = Router.Route;
RouteHandler = Router.RouteHandler;
DefaultRoute = Router.DefaultRoute;
var routes = (
<Route name="app" path="/" handler={OurSchoolsApp}>
<DefaultRoute name="home" handler={HomePage} />
<Route name="add-school" handler={AddSchoolPage} />
<Route name="calendar" handler={CalendarPage} />
<Route name="calendar-detail" path="calendar-detail/:id" handler={CalendarDetailPage} />
<Route name="info-detail" path="info-detail/:id" handler={InfoDetailPage} />
<Route name="info" handler={InfoPage} />
<Route name="news" handler={NewsListPage} />
<Route name="news-detail" path="news-detail/:id" handler={NewsDetailPage} />
<Route name="contacts" handler={ContactPage} />
<Route name="contact-detail" handler={ContactDetailPage} />
<Route name="settings" handler={SettingsPage} />
</Route>
);
Router.run(routes, function(Handler){
var mountNode = document.getElementById('app');
React.render(<Handler /> , mountNode);
});
Update with React v16 and ReactRouter v4.2.0 (October 2017):
class BackButton extends Component {
static contextTypes = {
router: () => true, // replace with PropTypes.object if you use them
}
render() {
return (
<button
className="button icon-left"
onClick={this.context.router.history.goBack}>
Back
</button>
)
}
}
Update with React v15 and ReactRouter v3.0.0 (August 2016):
var browserHistory = ReactRouter.browserHistory;
var BackButton = React.createClass({
render: function() {
return (
<button
className="button icon-left"
onClick={browserHistory.goBack}>
Back
</button>
);
}
});
Created a fiddle with a little bit more complex example with an embedded iframe: https://jsfiddle.net/kwg1da3a/
React v14 and ReacRouter v1.0.0 (Sep 10, 2015)
You can do this:
var React = require("react");
var Router = require("react-router");
var SomePage = React.createClass({
...
contextTypes: {
router: React.PropTypes.func
},
...
handleClose: function () {
if (Router.History.length > 1) {
// this will take you back if there is history
Router.History.back();
} else {
// this will take you to the parent route if there is no history,
// but unfortunately also add it as a new route
var currentRoutes = this.context.router.getCurrentRoutes();
var routeName = currentRoutes[currentRoutes.length - 2].name;
this.context.router.transitionTo(routeName);
}
},
...
You need to be careful that you have the necessary history to go back. If you hit the page directly and then hit back it will take you back in the browser history before your app.
This solution will take care of both scenarios. It will, however, not handle an iframe that can navigate within the page (and add to the browser history), with the back button. Frankly, I think that is a bug in the react-router. Issue created here: https://github.com/rackt/react-router/issues/1874
Using React Hooks
Import:
import { useHistory } from "react-router-dom";
In stateless component:
let history = useHistory();
Call the Event:
history.goBack()
Examples do use in event Button:
<button onClick={history.goBack}>Back</button>
or
<button onClick={() => history.goBack()}>Back</button>
import withRouter
import { withRouter } from 'react-router-dom';
Export your component as:
export withRouter(nameofcomponent)
Example, on button click, call goBack:
<button onClick={this.props.history.goBack}>Back</button>
Tested on react-router-dom v4.3
I think you just need to enable BrowserHistory on your router by intializing it like that : <Router history={new BrowserHistory}>.
Before that, you should require BrowserHistory from 'react-router/lib/BrowserHistory'
Here's an example using ES6
const BrowserHistory = require('react-router/lib/BrowserHistory').default;
const App = React.createClass({
render: () => {
return (
<div><button onClick={BrowserHistory.goBack}>Go Back</button></div>
);
}
});
React.render((
<Router history={BrowserHistory}>
<Route path="/" component={App} />
</Router>
), document.body);
React Router v6
useNavigate Hook is the recommended way to go back now:
import { useNavigate } from 'react-router-dom';
function App() {
const navigate = useNavigate();
return (
<>
<button onClick={() => navigate(-1)}>go back</button>
<button onClick={() => navigate(1)}>go forward</button>
</>
);
}
Codesandbox sample
Go back/forward multiple history stack entries:
<button onClick={() => navigate(-2)}>go two back</button>
<button onClick={() => navigate(2)}>go two forward</button>
Go to specific route:
navigate("users") // go to users route, like history.push
navigate("users", { replace: true }) // go to users route, like history.replace
navigate("users", { state }) // go to users route, pass some state in
useNavigate replaces useHistory to support upcoming React Suspense/Concurrent mode better.
this.context.router.goBack()
No navigation mixin required!
ES6 method without mixins using react-router, stateless function.
import React from 'react'
import { browserHistory } from 'react-router'
export const Test = () => (
<div className="">
<button onClick={browserHistory.goBack}>Back</button>
</div>
)
Go back to specific page:
import { useHistory } from "react-router-dom";
const history = useHistory();
const routeChange = () => {
let path = '/login';
history.push(path);
};
Go back to previous page:
import { useHistory } from "react-router-dom";
const history = useHistory();
const routeChange = () => {
history.goBack()
};
Check out my working example using React 16.0 with React-router v4. check out the code Github
Use withRouter and history.goBack()
This is the idea I am implementing...
History.js
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom'
import './App.css'
class History extends Component {
handleBack = () => {
this.props.history.goBack()
}
handleForward = () => {
console.log(this.props.history)
this.props.history.go(+1)
}
render() {
return <div className="container">
<div className="row d-flex justify-content-between">
<span onClick={this.handleBack} className="d-flex justify-content-start button">
<i className="fas fa-arrow-alt-circle-left fa-5x"></i>
</span>
<span onClick={this.handleForward} className="d-flex justify-content-end button">
<i className="fas fa-arrow-alt-circle-right fa-5x"></i>
</span>
</div>
</div>
}
}
export default withRouter(History)
PageOne.js
import React, { Fragment, Component } from 'react'
class PageOne extends Component {
componentDidMount(){
if(this.props.location.state && this.props.location.state.from != '/pageone')
this.props.history.push({
pathname: '/pageone',
state: {
from: this.props.location.pathname
}
});
}
render() {
return (
<Fragment>
<div className="container-fluid">
<div className="row d-flex justify-content-center">
<h2>Page One</h2>
</div>
</div>
</Fragment>
)
}
}
export default PageOne
p.s. sorry the code is to big to post it all here
This works with Browser and Hash history.
this.props.history.goBack();
This is a working BackButton component (React 0.14):
var React = require('react');
var Router = require('react-router');
var History = Router.History;
var BackButton = React.createClass({
mixins: [ History ],
render: function() {
return (
<button className="back" onClick={this.history.goBack}>{this.props.children}</button>
);
}
});
module.exports = BackButton;
You can off course do something like this if there is no history:
<button className="back" onClick={goBack}>{this.props.children}</button>
function goBack(e) {
if (/* no history */) {
e.preventDefault();
} else {
this.history.goBack();
}
}
For react-router v2.x this has changed. Here's what I'm doing for ES6:
import React from 'react';
import FontAwesome from 'react-fontawesome';
import { Router, RouterContext, Link, browserHistory } from 'react-router';
export default class Header extends React.Component {
render() {
return (
<div id="header">
<div className="header-left">
{
this.props.hasBackButton &&
<FontAwesome name="angle-left" className="back-button" onClick={this.context.router.goBack} />
}
</div>
<div>{this.props.title}</div>
</div>
)
}
}
Header.contextTypes = {
router: React.PropTypes.object
};
Header.defaultProps = {
hasBackButton: true
};
Header.propTypes = {
title: React.PropTypes.string
};
In react-router v4.x you can use history.goBack which is equivalent to history.go(-1).
App.js
import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Home from "./Home";
import About from "./About";
import Contact from "./Contact";
import Back from "./Back";
const styles = {
fontFamily: "sans-serif",
textAlign: "left"
};
const App = () => (
<div style={styles}>
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
<hr />
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
<Back />{/* <----- This is component that will render Back button */}
</div>
</Router>
</div>
);
render(<App />, document.getElementById("root"));
Back.js
import React from "react";
import { withRouter } from "react-router-dom";
const Back = ({ history }) => (
<button onClick={history.goBack}>Back to previous page</button>
);
export default withRouter(Back);
Demo:
https://codesandbox.io/s/ywmvp95wpj
Please remember that by using history your users can leave because history.goBack() can load a page that visitor has visited before opening your application.
To prevent such situation as described above, I've created a simple library react-router-last-location that watch your users last location.
Usage is very straight forward.
First you need to install react-router-dom and react-router-last-location from npm.
npm install react-router-dom react-router-last-location --save
Then use LastLocationProvider as below:
App.js
import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { LastLocationProvider } from "react-router-last-location";
// ↑
// |
// |
//
// Import provider
//
import Home from "./Home";
import About from "./About";
import Contact from "./Contact";
import Back from "./Back";
const styles = {
fontFamily: "sans-serif",
textAlign: "left"
};
const App = () => (
<div style={styles}>
<h5>Click on About to see your last location</h5>
<Router>
<LastLocationProvider>{/* <---- Put provider inside <Router> */}
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
<hr />
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
<Back />
</div>
</LastLocationProvider>
</Router>
</div>
);
render(<App />, document.getElementById("root"));
Back.js
import React from "react";
import { Link } from "react-router-dom";
import { withLastLocation } from "react-router-last-location";
// ↑
// |
// |
//
// `withLastLocation` higher order component
// will pass `lastLocation` to your component
//
// |
// |
// ↓
const Back = ({ lastLocation }) => (
lastLocation && <Link to={lastLocation || '/'}>Back to previous page</Link>
);
// Remember to wrap
// your component before exporting
//
// |
// |
// ↓
export default withLastLocation(Back);
Demo: https://codesandbox.io/s/727nqm99jj
I want to update the previous answers a bit.
If you are using react-router >v6.0 then the useHistory() is not the right way to go back. You will get an error as I guess useHistory() is not present in the latest version.
So this is the updated answer
// This is a React Router v6 app
import { useNavigate } from "react-router-dom";
function App() {
const navigate = useNavigate();
return (
<>
<button onClick={() => navigate(-2)}>
Go 2 pages back
</button>
<button onClick={() => navigate(-1)}>Go back</button>
<button onClick={() => navigate(1)}>
Go forward
</button>
<button onClick={() => navigate(2)}>
Go 2 pages forward
</button>
</>
);
}
Use this useNavigate() hook.
You can read the official doc for this transition from v5 to v6 here
https://reactrouter.com/docs/en/v6/upgrading/v5
What worked for me was to import withRouter at the top of my file;
import { withRouter } from 'react-router-dom'
Then use it to wrap the exported function at the bottom of my file;
export default withRouter(WebSitePageTitleComponent)
Which then allowed me to access the Router's history prop. Full sample code below!
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
import PropTypes from 'prop-types'
class TestComponent extends Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
event.preventDefault()
this.props.history.goBack()
}
render() {
return (
<div className="page-title">
<a className="container" href="/location" onClick={this.handleClick}>
<h1 className="page-header">
{ this.props.title }
</h1>
</a>
</div>
)
}
}
const { string, object } = PropTypes
TestComponent.propTypes = {
title: string.isRequired,
history: object
}
export default withRouter(TestComponent)
On react-router-dom v6
import { useNavigate } from 'react-router-dom';
function goBack() {
const navigate = useNavigate();
return <button onClick={() => navigate(-1)}>go back</button>
}
import { withRouter } from 'react-router-dom'
this.props.history.goBack();
I am using these versions
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
Step-1
import { useHistory } from "react-router-dom";`
Step-2
let history = useHistory();
Step-3
const goToPreviousPath = (e) => {
e.preventDefault();
history.goBack()
}
step-4
<Button
onClick={goToPreviousPath}
>
Back
</Button>
REDUX
You can also use react-router-redux which has goBack() and push().
Here is a sampler pack for that:
In your app's entry point, you need ConnectedRouter, and a sometimes tricky connection to hook up is the history object. The Redux middleware listens to history changes:
import React from 'react'
import { render } from 'react-dom'
import { ApolloProvider } from 'react-apollo'
import { Provider } from 'react-redux'
import { ConnectedRouter } from 'react-router-redux'
import client from './components/apolloClient'
import store, { history } from './store'
import Routes from './Routes'
import './index.css'
render(
<ApolloProvider client={client}>
<Provider store={store}>
<ConnectedRouter history={history}>
<Routes />
</ConnectedRouter>
</Provider>
</ApolloProvider>,
document.getElementById('root'),
)
I will show you a way to hook up the history. Notice how the history is imported into the store and also exported as a singleton so it can be used in the app's entry point:
import { createStore, applyMiddleware, compose } from 'redux'
import { routerMiddleware } from 'react-router-redux'
import thunk from 'redux-thunk'
import createHistory from 'history/createBrowserHistory'
import rootReducer from './reducers'
export const history = createHistory()
const initialState = {}
const enhancers = []
const middleware = [thunk, routerMiddleware(history)]
if (process.env.NODE_ENV === 'development') {
const { devToolsExtension } = window
if (typeof devToolsExtension === 'function') {
enhancers.push(devToolsExtension())
}
}
const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers)
const store = createStore(rootReducer, initialState, composedEnhancers)
export default store
The above example block shows how to load the react-router-redux middleware helpers which complete the setup process.
I think this next part is completely extra, but I will include it just in case someone in the future finds benefit:
import { combineReducers } from 'redux'
import { routerReducer as routing } from 'react-router-redux'
export default combineReducers({
routing, form,
})
I use routerReducer all the time because it allows me to force reload Components that normally do not due to shouldComponentUpdate. The obvious example is when you have a Nav Bar that is supposed to update when a user presses a NavLink button. If you go down that road, you will learn that Redux's connect method uses shouldComponentUpdate. With routerReducer, you can use mapStateToProps to map routing changes into the Nav Bar, and this will trigger it to update when the history object changes.
Like this:
const mapStateToProps = ({ routing }) => ({ routing })
export default connect(mapStateToProps)(Nav)
Forgive me while I add some extra keywords for people: if your component isn't updating properly, investigate shouldComponentUpdate by removing the connect function and see if it fixes the problem. If so, pull in the routerReducer and the component will update properly when the URL changes.
In closing, after doing all that, you can call goBack() or push() anytime you want!
Try it now in some random component:
Import in connect()
You don't even need mapStateToProps or mapDispatchToProps
Import in goBack and push from react-router-redux
Call this.props.dispatch(goBack())
Call this.props.dispatch(push('/sandwich'))
Experience positive emotion
If you need more sampling, check out: https://www.npmjs.com/package/react-router-redux
Simply use like this
<span onClick={() => this.props.history.goBack()}>Back</span>
The only solution that worked for me was the most simple. No additional imports needed.
<a href="#" onClick={() => this.props.history.goBack()}>Back</a>
Tks, IamMHussain
React Router uses the HTML5 History API, which builds on the browser history API to provide an interface to which we can use easily in React apps. History API . So without import anything (useHistory, etc)
for functional component:
<button onClick={()=>{ window.history.back() }}> Back </button>
for class component:
<button onClick={()=>{ this.window.history.back() }}> Back </button>
In react-router v6, when you want to go back to the previous page, you can do that with useNavigate:
Step 1:
import { useNavigate } from "react-router-dom";
Step2:
const navigate = useNavigate();
Step 3: if you want to go back to the previous page, use navigate(-1):
<button onClick={() => navigate(-1)}> Back </button>
If you are using react-router v6, when you want to go back to the previous page you can do that with the Link:
Step 1: you need to import Link from react-router-dom
import { Link } from 'react-router-dom';
Step 2: wrap up the button with Link like this. It works perfectly.
<Link to='..'>
<Button type='button'>Go Back</Button>
</Link>
Call the following component like so:
<BackButton history={this.props.history} />
And here is the component:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class BackButton extends Component {
constructor() {
super(...arguments)
this.goBack = this.goBack.bind(this)
}
render() {
return (
<button
onClick={this.goBack}>
Back
</button>
)
}
goBack() {
this.props.history.goBack()
}
}
BackButton.propTypes = {
history: PropTypes.object,
}
export default BackButton
I'm using:
"react": "15.6.1"
"react-router": "4.2.0"
if you are using react-native drawer navigation as main router in your application and want to control back button behavior and go back historically you can use to control back button.
<NavigationContainer>
<Drawer.Navigator
backBehavior="history">
// your screens come here
</Drawer.Navigator>
</NavigationContainer>
This piece of code will do the trick for you.
this.context.router.history.goBack()
According to https://reacttraining.com/react-router/web/api/history
For "react-router-dom": "^5.1.2",,
const { history } = this.props;
<Button onClick={history.goBack}>
Back
</Button>
YourComponent.propTypes = {
history: PropTypes.shape({
goBack: PropTypes.func.isRequired,
}).isRequired,
};