I am having a hard time getting react router v4 to push a programmatic history based on an if statement conditional. All of the routing works fine on a button click, but I simply cannot get the history to work. The error that I am getting is:
TypeError: Cannot read property 'push' of undefined
This is at the line
self.props.history.push('/picturemain')
So clearly, in my component it doesn't think that history is defined. I'm not sure what I am doing wrong however. Here is my routing page:
import React from 'react'
import { Switch, Route, BrowserRouter as Router } from 'react-router-dom'
import { injectGlobal, ThemeProvider } from 'styled-components'
import { HomePage, AboutPage, PictureSwapper, PostsPage, Posts1, Posts2, Posts3, Posts4, PostsArchive, MessagePage, PictureMain } from 'components'
const App = () => {
return (
<ThemeProvider theme={theme}>
<Router>
<div>
<Route path="/" component={Posts3} exact />
<Route path="/home" component={HomePage} exact />
<Route path="/about" component={AboutPage} exact />
<Route path="/posts" component={PostsPage} exact />
<Route path="/pictureswapper" component={PictureSwapper} exact />
<Route path="/message" component={MessagePage} exact />
<Route path="/postpages/1" component={Posts1} exact />
<Route path="/postpages/2" component={Posts2} exact />
<Route path="/postpages/3" component={Posts3} exact />
<Route path="/postpages/4" component={Posts4} exact />
<Route path="/postsarchive" component={PostsArchive} exact />
<Route path="/picturemain" component={PictureMain} exact />
</div>
</Router>
</ThemeProvider>
)
}
export default App
And here is my page with the conditionals that push to history. The conditionals successfully get to the backend, and the error is only thrown because history is undefined.
import React, { Component, PropTypes } from 'react'
import { Badge, IconButton, Heading, Paragraph, ParagraphHolder,
PrimaryNavigation,
SecondaryNavigation, TertiaryNavigation,
Caption, Link, ParagraphSmall, AlignContainer,
SubHeader, PictureMain} from 'components'
import renderIf from 'render-if'
import styled from 'styled-components'
import axios from 'axios'
import {
BrowserRouter as Router,
Route,
Redirect,
Switch
} from 'react-router-dom';
class PictureLogin extends Component{
static propTypes = {
history: PropTypes.object.isRequired
}
constructor(props){
super(props);
this.state = {
name: '',
password: '',
redirect: ''
}
}
registerClick(e){
e.preventDefault();
var self = this;
axios.post('http://localhost:5000/register', {
name: this.state.name,
password: this.state.password
})
.then((response)=>{
console.log('response from the python call ', response.data);
if(response.data === 'usersuccessfullyadded'){
self.props.history.push('/picturemain')
}
})
.catch(()=>{
console.log('python axios error');
});
}
loginClick(e){
e.preventDefault();
var self = this;
axios.post('http://localhost:5000/login', {
name: this.state.name,
password: this.state.password
})
.then((response)=>{
console.log('response from the python call ', response.data);
if(response.data === 'passwordsmatch'){
console.log(self.props)
self.props.history.push('/picturemain')
}
})
.catch((err)=>{
console.log('python axios error');
console.log('and the error is ', err);
});
}
resetRedirect(){
this.setState({
redirect: ""
})
}
render(){
return(
<FlexContainer>
<FlexRow>
<div>Login</div>
<input value={this.state.name}
onChange={(e)=>{this.setState({name: e.target.value})}}
type="username" name="username" placeholder="User Name"/><br/>
<input value={this.state.password}
onChange={(e)=>{this.setState({password: e.target.value})}}
type="password" name="password" placeholder="Password"/><br/>
<button onClick={(e)=>this.registerClick(e)}>Register</button>
<button onClick={(e)=>this.loginClick(e)}>Login</button>
</FlexRow>
</FlexContainer>
)
}
}
export default PictureLogin
FlexContainer and FlexRow are my own styled components which are not declared here. That's ok as the styling is in this sheet, I just took it out for readability.
EDIT: Someone linked to a possible dupe here: How to navigate dynamically using react router dom. The fix was supposed to be that I add this to the header import {withRouter} from 'react-router-dom';
and export like this export default withRouter(PictureLogin);
. I've made those changes and there IS a change - now I am routing, but to a blank page! So...I'm going to leave this question open as there is something clearly going wrong. The page I am routing to has renderable data, but it is not rendering for some reason. This is not a fix that works.
The component I am rendering is a simple hello world to make sure that I am not including anything weird that would break it. Here is the component that I am trying to route to:
import React, { Component } from 'react'
import renderIf from 'render-if'
import styled from 'styled-components'
import axios from 'axios'
class PictureMain extends Component{
constructor(props){
super(props);
this.state = {
}
}
render(){
return(
<div>
hello world
</div>
)
}
}
export default PictureMain