I will try and make this as short and sweet as possible while being detailed and descriptive. When my application initializes or loads for the first time, it makes an api
call to fetch some blog
data. Here is what that looks like more or less:
As you can see the api
successfully returns the blogPosts
. I then reference these blogPosts
in another component using createStructuredSelector
from the reselect
library. Here is the code:
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { compose } from 'redux';
import VisionBlogItem from '../../components/VisionBlogItem';
import { getBlogItem, getFollowingBlogItems } from './selectors';
export class VisionBlogItemPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props, context) {
super(props, context);
this.state = {
};
}
render() {
return (
<div>
{this.props.blogItem && <VisionBlogItem blog={this.props.blogItem} blogItems={this.props.blogItems} />}
</div>
);
}
}
VisionBlogItemPage.propTypes = {
dispatch: PropTypes.func.isRequired,
location: PropTypes.shape({
pathname: PropTypes.string.isRequired,
}),
blogItem: PropTypes.object,
blogItems: PropTypes.array,
};
VisionBlogItemPage.defaultProps = {
blogItem: {},
blogItems: [],
};
const mapStateToProps = (state, ownProps) => {
return createStructuredSelector({
blogItem: getBlogItem(ownProps.location.pathname.match(/([^/]*)\/*$/)[1]),
blogItems: getFollowingBlogItems(ownProps.location.pathname.match(/([^/]*)\/*$/)[1])
});
};
function mapDispatchToProps(dispatch) {
return {
dispatch,
};
}
const withConnect = connect(mapStateToProps, mapDispatchToProps);
export default compose(
withConnect,
)(VisionBlogItemPage);
What these selector methods are doing, getBlogItem
and getFollowingBlogItems
, are checking the props location pathname end slug and using it to iterate and array to find the needed blog in the Redux State Store
. They then get set to the props named blogItem
and blogItems
to be passed to the presentational component
to render. That presentational component looks something like this:
At the bottom of this presentational component are some links that will change the slug name. So if I'm at localhost:3000/blogPosts/blog-post-0
and I clicked on one of the three blog posts at the bottom, it would then change the url to localhost:3000/blogPosts/blog-post-1
or blog-post-2
, blog-post-3
, etc. These blog posts at the bottom are links from react-router-dom
and the code is written as such:
<Link to={props.blogItems[2].fields.slug} style={styles.seeMoreLink}>
<img src={props.blogItems[2].fields.articleImage.fields.file.url} style={styles.seeMoreImg} alt="" key="2" />
</Link>
So the idea is that it changes the slug of the url and renders the appropriate blog post. However, this is not what is occurring. The url slug does change and I can even see in my container component
that the props update and change as well. The location pathname changes from blog-post-1
to blog-post-2
. My question then lies why does my component not re-render? I am aware of the life-cycle method of componentWillReceiveProps
, but I do not know how to use it in conjunction with something like createStructuredSelector
from reselect
. Anyone who could possibly give me a clear path as to how I am suppose to handle this it would be greatly appreciated!