Reputation: 866
I have posts and each post has comments, when I am adding a new comment the change is displayed (rendered) until I refresh the page manually but I can see in redux-dev tools that ADD_COMMENT action is being called and state of post is changing. What I want is to show the comment on page as soon as it is added to database. (State change and rendering works fine on Post Add,Delete,Update).
posts.js (contains all the posts):
class Posts extends Component {
static propTypes = {
posts: PropTypes.array.isRequired,
getPosts: PropTypes.func.isRequired,
deletePost: PropTypes.func.isRequired,
};
componentDidMount() {
this.props.getPosts();
}
onDelete = (id) => {
this.props.deletePost(id);
};
render() {
return (
<React.Fragment>
{this.props.posts.map((_p) => (
<Post _p={_p} onDelete={this.onDelete} key={_p.id} />
))}
</React.Fragment>
);
}
}
const mapToPropTypes = (state) => {
return { posts: state.posts.posts };
};
export default connect(mapToPropTypes, { getPosts, deletePost })(Posts);
post.js (Single post):
class Post extends Component {
handleDelete = (id) => {
this.props.onDelete(id);
};
render() {
var _p = this.props._p;
return (
<div className="row pt-3 pb-5">
<div className="col-lg-8">
<h1 className="mt-4">{_p.title}</h1>
{/*.... POST RELATED INPUTS ....*/}
<hr />
{/* Comment Form */}
<CommentForm postID={_p.id} />
{/* COMMENT COMPONENT */}
{_p.comments.map((_c) => (
<Comment key={_c.id} comment={_c} />
))}
</div>
</div>
);
}
}
export default connect()(Post);
commentForm.js:
class CommentForm extends Component {
state = {
name: "",
commentBody: "",
};
static propTypes = {
addComment: PropTypes.func.isRequired,
};
handleSubmit = (e) => {
e.preventDefault();
const comment = {
body: this.state.commentBody,
post: this.props.postID,
name: this.state.name,
};
this.props.addComment(comment);
};
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
render() {
const { name, commentBody } = this.state;
return (
<div className="card my-4">
<h5 className="card-header">Leave a Comment:</h5>
<div className="card-body">
<form onSubmit={this.handleSubmit}>
<div className="form-group">
<label>Title:</label>
<input
type="text"
name="name"
value={name}
onChange={this.handleChange}
className="form-control"
/>
</div>
<div className="form-group">
<textarea
className="form-control"
name="commentBody"
value={commentBody}
onChange={this.handleChange}
rows="3"
></textarea>
</div>
<button type="submit" className="btn btn-primary">
Submit
</button>
</form>
</div>
</div>
);
}
}
export default connect(null, { addComment })(CommentForm);
comment.js:
const Comment = (props) => {
const _c = props.comment;
return (
<div className="media mb-4" key={_c.id}>
{/* ... COMMENT RELATED OUTPUTS ...*/}
</div>
);
};
export default connect(null)(Comment);
reducer:
case ADD_COMMENT:
state.posts.map((_p) => {
if (_p.id === action.payload.post)
_p.comments = [..._p.comments, action.payload];
});
return state;
addComment function:
export const addComment = (comment) => (dispatch, getState) => {
axios
.post("http://127.0.0.1:8000/api/comments/", comment)
.then((res) => dispatch({ type: ADD_COMMENT, payload: res.data }))
.catch((err) => console.log(err));
};
Upvotes: 0
Views: 219
Reputation: 131
Maybe the problem is due to the state that is not considered as modified.
I saw 2 things in your reducer :
Like this :
let modifiedPosts = state.posts.map((_p) => {
if (_p.id === action.payload.post)
_p.comments = [..._p.comments, action.payload];
});
return Object.assign( {}, state, {
posts: modifiedPosts
} );
Upvotes: 2