How can I manually stop the subscription and clean the collection on the client when you switch route via react-router?
The fact is that if I go to the page where there is a component subscribed to, such as “top 10 news” page, where published all the news, I see, as a container of news component performing a normal search the collection first finds objects with subscription last page.
export default createContainer((props)=>{
let {limitCount, userId} = props;
let query = (userId)?{'userId':userId}:{};
var handle = Meteor.subscribe('news_preview', query,limitCount);
var posts = Post.find(query, {sort:{createdAt:-1}}).fetch(); //Here, the container finds documents to which another component has been signed.
var needWait = !!handle.ready()&&!!posts;
return {
needWait:!needWait,
posts:posts
}
}, PostList)
In details. With the logic description
PostListContainer
This is a sample of NewsList component, with infinity scroll and subscribtion container. Is just detect scroll, and pass limitCount to child component.
export default class PostListContainer extends Component{
constructor(props){
super(props)
this.state={
limitCount:10,
}
this.handleScroll = this.handleScroll.bind(this);
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll, false);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll, false);
}
handleScroll(event) {
let documentHeight = $(document).height(); //jquery is bad idea, i know
let windowHeight = $(window).height();
let scrollPosition = $(window).scrollTop();
let isLoading = this.refs.PostList.data.needWait;
if(scrollPosition+windowHeight>=documentHeight && !isLoading){
this.uppendSkipCount()
}
}
uppendSkipCount(){
let limitCount = this.state.limitCount;
this.setState({
limitCount:limitCount+5
});
}
render(){
let userId = (this.props.userId)?this.props.userId:undefined;
return(
<div>
<PostList ref="PostList" limitCount={this.state.limitCount} userId={userId} />
</div>
)
}
}
PostList
This component get properties, subscribe and render child components.
export class PostList extends Component {
constructor(props){
super(props);
}
postList(){
return(
<Masonry>
{this.props.posts.map((post)=>(
<div className="col-xs-12 col-sm-6 col-md-6 col-lg-4" key={post._id}>
<PostPreview post={post}/>
</div>
))}
</Masonry>
)
}
render() {
let content = (this.props.posts)?this.postList():undefined;
let loading = (this.props.needWait)?<Loading />:undefined;
return(
<div>
{content}
{loading}
</div>
)
}
}
export default createContainer((props)=>{
let {limitCount, userId} = props;
let query = (userId)?{'userId':userId}:{};
var handle = Meteor.subscribe('news_preview', query,limitCount);
var posts = Post.find(query, {sort:{createdAt:-1}}).fetch();
var needWait = !!handle.ready()&&!!posts;
return {
needWait:!needWait,
posts:posts
}
}, PostList)
And it work goood. But if i will come on the page from page that contain for example BestNews component i will get Posts object from that in first iteration:(
export class BestNews extends Component {
constructor(props){
super(props);
}
componentWillUnmount(){
this.props.handle.stop(); / looks like it help
}
goToPage(post){
browserHistory.push(`/news/item/${post._id}`);
}
bestPosts(){
return bestPosts = this.props.posts.map((post)=>{
return(
<div key={post._id}>
<ListItem
onTouchTap={()=>this.goToPage(post)}
leftAvatar={<Avatar src={post.author().getAvatar().link()} />}
rightIcon ={<ActionChromeReaderMode />}
primaryText={post.title}
secondaryText={post.description}
/>
<Divider />
</div>
)
});
}
render() {
let content = (this.props.needWait)?<Loading />:this.bestPosts();
return (
<div className="box-margin">
<Paper zDepth={1}>
<div className="row middle-xs center-xs">
<div className="col-xs-12">
<h2 style={{fontWeight:'300'}}>Интересные новости</h2>
</div>
</div>
<div className="row start-xs">
<div className="col-xs-12">
<List>
<Divider />
{content}
</List>
</div>
</div>
</Paper>
</div>
)
}
}
export default createContainer((props)=>{
var handle = Meteor.subscribe('best_news');
var posts = Post.find({}, {sort:{likes:-1}, limit:5}).fetch();
var needWait = !handle.ready() && !posts;
return {
handle:handle,
needWait:needWait,
posts:posts
}
}, BestNews)
After a moment, the container will complete its membership and will give us the relevant objects …
How can I check that when linking the previous container has stopped its subscription and deleted objects?