I’ve got two apps that I am working on at the moment and both are using React + Meteor. I’m running into a weird problem where some components are reactive and others aren’t. For instance, the following AdminPostItem component requires a page refresh to show current information:
Here is the parent component:
C.Admin = React.createClass({
propTypes: {},
mixins: [
ReactMeteorData
],
getInitialState() {
return {}
},
getMeteorData() {
var postsSub = Meteor.subscribe('all_posts');
return {
currentUser: Meteor.user(),
postsLoading: !postsSub.ready(),
posts: Posts.find({}, {sort: {created_at: -1}})
};
return {
currentUser: Meteor.user()
};
},
renderPosts() {
return this.data.posts.map((post) => {
return (
<C.AdminPostItem key={ post._id } post={ post } />
)
});
},
addPost() {
var title = $('[name="title"]').val();
Meteor.call("posts/insert", title, function(err, res) {
if (err) {
console.log(err.reason);
} else if (res) {
$('#add-post').modal('toggle');
FlowRouter.go("PostEdit", {_id: res}, {});
}
});
},
render() {
return (
<div className="admin-container">
<div className="admin-page-header">
<h1>Posts</h1>
<a href="#" className="pull-right" data-toggle="modal" data-target="#add-post">Add Post</a>
<div className="modal fade" id="add-post" tabIndex="-1" role="dialog" aria-labelledby="myModalLabel">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title" id="myModalLabel">Add Post</h4>
</div>
<div className="modal-body">
<form id="add-post-form">
<div className="form-group">
<label htmlFor="title">Title</label>
<input type="text" className="form-control" name="title"/>
</div>
</form>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary" onClick={ this.addPost }>Add Post</button>
</div>
</div>
</div>
</div>
</div>
<div className="admin-page-body">
{ this.renderPosts() }
</div>
</div>
)
}
});
I’m using Bootstrap so sorry for the excessive markup
Here is the child component that won’t update (the parent doesn’t update when I remove posts either):
C.AdminPostItem = React.createClass({
propTypes: {
post: React.PropTypes.object.isRequired
},
getInitialState() {
return {}
},
shouldComponentUpdate() {
return true;
},
removePost() {
if (confirm("Are you sure you wan't to remove this post?")) {
Meteor.call('posts/remove', this.props.post._id, function(err) {
if (err) {
console.log(err.reason);
} else {
console.log("Successfully removed post");
}
});
}
},
togglePublish(e) {
const self = this;
let published = $(e.target).html().trim() === "Published";
let modifier = {
'$set': {}
};
if (published) {
modifier['$set'].status = "Draft";
} else {
modifier['$set'].status = "Published";
}
Meteor.call('posts/update', modifier, this.props.post._id, function(err) {
if (err) {
console.log(err.reason);
} else {
self.forceUpdate()
}
});
},
render() {
let { post } = this.props;
let link = FlowRouter.path("PostPage", { slug: post.slug }, {});
let edit_link = FlowRouter.path("PostEdit", { _id: post._id }, {});
return (
<div className="admin-post-item" key={ post._id }>
<h4><a href={ link }>{ post.title }</a></h4>
<span className="post-status" onClick={ this.togglePublish }>{ post.status } </span><span className="time-ago">Last edited <span data-livestamp={ post.updated_at }></span> - </span>
<span><a href={ edit_link } className="edit-post">Edit </a>
or
<a href="#" onClick={ this.removePost } className="remove-post"> Remove</a></span>
</div>
)
}
});
To recap: When I change the underlying data for a post the AdminPostItem component doesn’t change. In addition, when I remove a post the Admin component doesn’t update and remove the post from the list.
I may be messing something up here, but I am new to React and have no idea why this isn’t reactive. Please let me know if you can spot what I’m doing wrong.