Why does my React component stay in the DOM after navigating to another page?
I have a simple application with a home screen, a main blog list and then a blog page. Moving from the home screen to the blog list and back works as expected. When I click on one of the blog posts, the app navigates to the page and displays the blog post. But when I go back to the main blog list, the blog post is now at the very bottom of the blog list. And if I then go back to the home page the same, the blog post is in the DOM behind the home page graphic.
I am using 4.1 reactive router.
It has to do with my route setup ?
import React, { Component } from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import NavBar from './components/NavBar'
import Blog from './pages/blog'
import Home from './pages/home'
import Post from './pages/post'
import './css/App.css'
class App extends Component {
render() {
return (
<Router>
<div className="App">
<NavBar />
<Route exact path='/' component={Home} />
<Route path='/blog' component={Blog} />
<Route path='/post/:slug' component={Post} />
</div>
</Router>
)
}
}
export default App
Or with my post component ?
import React from 'react'
import fetch from 'isomorphic-unfetch'
import NavBar from '../components/NavBar'
import dateUtils from '../utilities/DateAndTime'
const classNames = require('classnames')
class Post extends React.Component {
constructor(props) {
super(props)
this.state = {
blogObject: null,
fetchBlogObject: false
}
this.fetchBlogObject = this.fetchBlogObject.bind(this)
this.createMarkup = this.createMarkup.bind(this)
this.assignStyleToCoverImage = this.assignStyleToCoverImage.bind(this)
this.formatDateString = this.formatDateString.bind(this)
}
componentWillMount() {
this.fetchBlogObject()
}
componentWillReceiveProps() {
this.fetchBlogObject()
}
fetchBlogObject() {
console.log('fetching')
this.setState({ fetchBlogObject: true })
fetch(`*******************`)
.then(response => response.json())
.then((responseJson) => {
console.log(responseJson)
this.setState({ blogObject: responseJson.object })
})
}
createMarkup(stringToConvertToHtml) {
return { __html: stringToConvertToHtml }
}
assignStyleToCoverImage() {
const style = {
background: `url(${this.state.blogObject.metadata.hero.url})`,
height: '35vh',
backgroundSize: 'cover',
backgroundPosition: 'center'
}
return style
}
formatDateString(dateString) {
console.log(dateString)
const d = `${dateUtils.returnMonthFromISODateString(dateString)} ${dateUtils.returnDateNumberFromISOString(dateString)}, ${dateUtils.returnFullYearFromISOString(dateString)} by Phil Andrews`
return d
}
render() {
const postContainerClasses = classNames({
'post-container': true
})
const postBodyClasses = classNames({
'post-body': true
})
return (
<div>
<NavBar />
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)
}
}
export default Post
Or using my blog list button to go to the post page?
<Link id={this.props.blogObject.slug} to={`/post/${this.props.blogObject.slug}`}>
<button className='blog-button' style={buttonStyle} id={this.props.blogObject.slug} />
</Link>
source to share
I'm not sure why it will continue to display the entire component, but if I get rid of <NavBar />
in the component post
, the problem goes away.
Doesn't work :
return (
<div>
<NavBar />
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)
IN
return (
<div>
{this.state.blogObject ?
<div className={postContainerClasses} >
<div className='header-image' style={this.assignStyleToCoverImage(this.state.blogObject)} />
<div className='post-body-padding'>
<div className='post-header-info'>
<h1 className='post-title'>{this.state.blogObject.title}</h1>
<h4 className='post-date'>{this.formatDateString(this.state.blogObject.created_at)}</h4>
</div>
<div className={postBodyClasses} dangerouslySetInnerHTML={this.createMarkup(this.state.blogObject.content)} />
</div>
</div>
: <div>Loading...</div>
}
</div>
)
source to share