Reputation: 3094
I am using react-router with react js and i following their documentation but facing this error
while compiling it shows the error,
TypeError: _this.props.history is undefined
this is my index.js file
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={App}>
</Route>
</Router>
,
document.getElementById('root')
);
and this is my App.js file
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
headerText: "Props from Header.",
contentText: "Props from content."
};
}
render() {
return (
<div className="App">
<ul>
<li><a href="">Home</a></li>
<li><a href="">Home</a></li>
<li><a href="">Home</a></li>
</ul>
</div>
);
}
}
export default App;
Upvotes: 47
Views: 90683
Reputation: 1985
I was getting this issue because I was trying to use props.history.push()
with RRD v6, but v6 has scrapped the useHistory
hook and instead uses the useNavigate
hook.
For example:
import {useNavigate} from 'react-router-dom';
const navigate = useNavigate();
navigate('/path');
See this link for more info: https://reactrouter.com/en/main/hooks/use-navigate
Upvotes: 0
Reputation: 1841
I have problems with my Form component.
this.props.history.push('/') is undefined.
to solve this i've added
import {withRouter} from 'react-router-dom'
And then export default component as:export default withRouter(connect(mapStateToProps)(CustomForm));
import React from "react";
import { Form, Input, Button } from "antd";
import { connect } from "react-redux";
import {withRouter} from 'react-router-dom'
import axios from "axios";
const FormItem = Form.Item;
class CustomForm extends React.Component {
handleFormSubmit = async (event, requestType, articleID, ) => {
event.preventDefault();
const postObj = {
title: event.target.elements.title.value,
content: event.target.elements.content.value
}
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.headers = {
"Content-Type": "application/json",
Authorization: `Token ${this.props.token}`,
};
if (requestType === "post") {
await axios.post("http://127.0.0.1:8000/api/create/", postObj)
.then(res => {
if (res.status === 201) {
this.props.history.push(`/`);
}
})
} else if (requestType === "put") {
await axios.put(`http://127.0.0.1:8000/api/${articleID}/update/`, postObj)
.then(res => {
if (res.status === 200) {
this.props.history.push(`/`);
}
})
}
};
render() {
return (
<div>
<Form
onSubmit={event =>
this.handleFormSubmit(
event,
this.props.requestType,
this.props.articleID
)
}
>
<FormItem label="Title">
<Input name="title" placeholder="Put a title here" />
</FormItem>
<FormItem label="Content">
<Input name="content" placeholder="Enter some content ..." />
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit">
{this.props.btnText}
</Button>
</FormItem>
</Form>
</div>
);
}
}
const mapStateToProps = state => {
return {
token: state.token
};
};
export default withRouter(connect(mapStateToProps)(CustomForm));
I hope this is useful for someone. I am using Django as a backend
Upvotes: 7
Reputation: 3427
I was trying to use history
in the functional component and it was undefined because I was trying to access it with props
.
According to the docs, we need to use useHistory
hook to access the history. Here is the sample code according to the docs.
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
You can check this link for more understanding.
Upvotes: 4
Reputation: 894
This works for me >>>
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
change the 'react-router' with 'react-router-dom', and Router with BrowserRouter as Router.
Like this >>>
import { BrowserRouter as Router, Route, browserHistory, IndexRoute } from 'react-router-dom';
Upvotes: 3
Reputation: 429
Check that if there are any components that you haven't linked to router or any links that is not necessary among your components.
Besides if you have <Router><Link>...</Link></Router>
in one of your clickable components it might crash your work.
Hope it might help.
Upvotes: 0
Reputation: 8635
I had something like:
<Router>
<HeaderComponent/>
<Router exact path="/" component={Home}/>
<Router path="/auth" component={AuthLayout}/>
<FooterComponent/>
</Router>
and AuthLayout
was a component in which I was switching between SignIn
and SignUp
components, like below:
<div>
{ login ? <SignIn/> : <SignUp/> }
</div>
I faced this error of this.props.history is not a function
inside these components. It was because I hadn't used those components directly inside the router. I had access to this.props.history
inside the AuthLayout
and I had to pass it to its children.
So I did it:
<div>
{ login ? <SignIn history={this.props.history}/> : <SignUp history={this.props.history}/> }
</div>
and the problem solved.
Upvotes: 2
Reputation: 392
For me the solution was to change
1) component as child
<Route path="/path">
<MyComponent/>
</Route>
to
2) component as the "component" prop
<Route path="/path" component={MyComponent}>
</Route>
In both ways it renders, so it was very confusing for me, in examples they provide code as in first example. (I used the version 5.1.2 of the "react-router-dom" package at the moment).
Update
You can also use this way (for child components (children of "MyComponent") works only this one)
import {withRouter} from 'react-router-dom';
const componentClassWithHistory = withRouter(ChildComponent);
export {componentClassWithHistory as ChildComponent};
or for default export
export default withRouter(ChildComponent)
or for typescript
const componentClassWithHistory = (withRouter(ChildComponent as any) as any);
export {componentClassWithHistory as ChildComponent};
Source: https://reacttraining.com/react-router/core/api/withRouter
Hope it helps someone.
Upvotes: 16
Reputation: 1994
This should be done in the component that is being routed to. In this case, it is App component. Therefore, in App.js, import "createBrowserHistory" and do it as follows:
import React, { Component } from 'react';
import './App.css';
import { createBrowserHistory } from "history";
class App extends Component {
constructor(props){
super(props);
this.history = createBrowserHistory();;
this.state = {
headerText: "Props from Header.",
contentText: "Props from content."
};
}
render() {
return (
<div className="App">
<ul>
<li><a href="">Home</a></li>
<li><a href="">Home</a></li>
<li><a href="">Home</a></li>
</ul>
</div>
);
}
}
export default App;
Upvotes: 0
Reputation: 1958
I encountered this problem when trying to instantiate my own Router rather than using one of the built-in ones, to deal with an issue of having access to the history:
history.js
import { createHashHistory as createHistory } from 'history'
export default createHistory()
root.jsx
import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
<Route path="/test" component={Test}/>
</Router>
In my case, the trouble was that I had a version of the history
package locked at v2.1.2, while react-router
was depending on a v4.x version of history
in its own dependencies. So the built-in routers instantiated fine using the newer history
, but when I tried to do it myself I was pulling in the older history
and getting an incompatible object.
Upvotes: 2
Reputation: 73
It seems to me that this.props.history is not defined, because you did not pass the routeProps to the component you want to render.
Change your routes as follows:
<Route path="/home" render={(routeProps) => <Home {...routeProps}/>} />
You can also pass other props to the rendered components using this method.
Upvotes: 4
Reputation: 749
The below solution works for me in ReactDOM.render:
<BrowserRouter>
<Switch>
<Route path="/home" component={Home} />
<Route path="/user" component={User} />
<Route path="*" component={page404} />
</Switch>
</BrowserRouter>
It use multiple Routing.
Upvotes: 0
Reputation: 10961
This is because things changed in React Router starting with 4.0.0. You should now use BrowserRouter
from react-router-dom
package when you were using browserHistory
. So your code will looks like:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import { BrowserRouter, Route } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<Route path="/" component={ App }/>
</BrowserRouter>, document.getElementById('root')
);
Of course, you'll need to install react-router-dom
first.
Also note that if you're using more than one Route
element, you'll have to use a Switch
as explained in this answer.
Upvotes: 39
Reputation: 115
Are you using npm? I had the same problem with "react-router": "^4.0.0" in my package.json. Changing it to "react-router": "^3.0.2" solved my problem.
Upvotes: 7