我非常难以更改商店和渲染组件。现在,我正在尝试制作一个具有注释的简单博客应用程序,每个注释都是一个对象,其对象嵌套在每个博客对象中。我知道这很可能是由于我的“ COMMENT”减速器引起的,但是我也会张贴我认为也是相关的组件。
这是博客状态的样子:
blogs: [
{
likes: 0,
comments: [
{
author: 'Username1',
user: '5f74f7a8323eed75cf95193b',
content: 'This is a blog post!',
createdAt: '2020-11-08 01:30:54',
id: '5fa7bacef054babc8ecdd37c'
},
{
author: 'Username1',
user: '5f74f7a8323eed75cf95193b',
content: 'This is a blog post!',
createdAt: '2020-11-08 01:30:54',
id: '5fa7bacef054babc8ecdd37c'
},
],
title: 'Blogtitle',
author: 'Username1',
url: 'siteurl',
user: {
username: 'Username1',
name: 'John Joseph',
id: '5f74f7a8323eed75cf95193b'
},
createdAt: '2020-11-08 01:30:51',
id: '5fa7bacbf054babc8ecdd37b'
}
],
以下是博客的精简文件:
import blogService from '../services/blogs';
import { changeNotification } from './notificationReducer';
const blogReducer = (state = [], action) => {
switch (action.type) {
case 'INIT_BLOGS':
return action.data;
case 'ADD_BLOG': {
return [...state, action.data];
}
case 'LIKE': {
const idToLike = action.data.id;
const blogToLike = state.find((b) => b.id === idToLike);
const likedBlog = {
...blogToLike,
likes: action.data.likes,
};
return state.map((blog) => (blog.id !== idToLike ? blog : likedBlog));
}
case 'COMMENT': {
return state.map((blog) => {
if (blog.id === action.id) {
return { ...blog, comments: { ...action.data.comments } };
}
return blog;
});
}
case 'GET_COMMENTS': {
console.log(action.data);
return state;
}
case 'DELETE_BLOG': {
const filteredBlogs = state.filter((blog) => blog.id !== action.data._id);
return filteredBlogs;
}
default:
return state;
}
};
export const initializeBlogs = () => async (dispatch) => {
const blogs = await blogService.getAll();
console.log(blogs);
dispatch({
type: 'INIT_BLOGS',
data: blogs,
});
};
export const createBlog = (returnedBlog) => async (dispatch) => {
const newBlog = await blogService.create(returnedBlog);
dispatch({
type: 'ADD_BLOG',
data: newBlog,
});
};
export const likeBlog = (blogObject) => async (dispatch) => {
const updatedBlog = await blogService.put(blogObject);
console.log(updatedBlog);
await dispatch({
type: 'LIKE',
data: updatedBlog,
});
dispatch(changeNotification(`You liked ${blogObject.author}'s post`, 3000));
};
export const addComment = (incomingComment, blogId) => async (dispatch) => {
const updatedBlog = await blogService.comment(incomingComment, blogId);
console.log(updatedBlog);
await dispatch({
type: 'COMMENT',
data: updatedBlog,
});
};
export const getComments = (blogId) => async (dispatch) => {
const retrievedBlog = await blogService.getComments(blogId);
console.log(retrievedBlog);
await dispatch({
type: 'GET_COMMENTS',
data: retrievedBlog,
});
};
export const deleteBlog = (blogObject) => async (dispatch) => {
await blogService.remove(blogObject);
await dispatch({
type: 'DELETE_BLOG',
data: blogObject,
});
dispatch(
changeNotification(`You deleted the post title: ${blogObject.title}`, 3000)
);
};
export default blogReducer;
以下是“评论”组件:
const Comments = ({ blog }) => {
const [comment, setComment] = useState('');
const user = useSelector((state) => state.user.id);
const dispatch = useDispatch();
const classes = commentStyles();
const createComment = (event, blogId) => {
event.preventDefault();
const date = moment().format('YYYY-MM-DD HH:mm:ss');
const newComment = { content: comment, user, createdAt: date };
dispatch(addComment(newComment, blogId));
dispatch(changeNotification(`Your comment has been added`, 3000));
dispatch(initializeBlogs());
};
return (
<div>
<h3>Comments:</h3>
<form
onSubmit={(event) => {
createComment(event, blog.id);
}}
>
<input
type="text"
name="comment"
value={comment}
onChange={({ target }) => setComment(target.value)}
/>
<button type="submit">add comment</button>
</form>
<hr />
{blog.comments.map((c, i) => (
<div
style={{ borderBottom: '1px solid black', marginBottom: '1em' }}
key={i}
className={classes.comment}
>
<p className={classes.author}>
{c.author} <span>{moment(c.createdAt).fromNow()}</span>
</p>
<p>{c.content}</p>
</div>
))}
</div>
);
};
const mapStateToProps = (state, ownProps) => ({
user: state.user,
});
export default connect(mapStateToProps)(Comments);
哪个是BlogView的孩子:
const BlogView = ({ blog, user }) => {
const dispatch = useDispatch();
const history = useHistory();
const howLongAgo = moment(blog.createdAt, 'YYYY-MM-DD HH:mm:ss').fromNow();
const like = () => {
const likedBlog = {
user: blog.user.id,
likes: blog.likes,
author: blog.author,
title: blog.title,
url: blog.url,
_id: blog.id,
};
dispatch(likeBlog(likedBlog));
};
const remove = () => {
if (blog.user.id !== user.id) {
dispatch(
changeNotification(
`You are not authorized to delete this post`,
3000,
true
)
);
return;
}
if (window.confirm(`Do you really want to delete "${blog.title}"?`)) {
const blogObject = {
user: blog.user.id,
author: blog.author,
title: blog.title,
url: blog.url,
_id: blog.id,
};
history.push('/');
dispatch(deleteBlog(blogObject));
}
};
return (
<div>
<h1>{blog.title}</h1>
<p>
<a href={blog.url}>{blog.url}</a>
</p>
<br />
<p>
Likes: {blog.likes}
<button onClick={like} type="button">
like
</button>
</p>
<p>
added by <Link to={`/users/${blog.user.id}`}>{blog.author}</Link> at{' '}
{howLongAgo}
</p>
<button onClick={remove} type="button">
delete
</button>
<hr />
<div>
<h3>{blog.title}</h3>
<br />
<p>This is the blog's content.</p>
</div>
<Comments blog={blog} />
</div>
);
};
const mapStateToProps = (state) => ({
user: state.user,
});
export default connect(mapStateToProps)(BlogView);