02_lesson: Added ReactionButton for emoji thumbs up/down

02_lesson
Jason Zhu 2023-03-07 15:28:14 +11:00
parent 1d970d5879
commit 47e543f2b4
3 changed files with 67 additions and 5 deletions

View File

@ -1,7 +1,8 @@
import { useSelector } from "react-redux"; import { useSelector } from 'react-redux';
import { selectAllPosts } from "./postsSlice"; import { selectAllPosts } from './postsSlice';
import PostAuthor from "./PostAuthor"; import PostAuthor from './PostAuthor';
import TimeAgo from "./TimeAgo"; import TimeAgo from './TimeAgo';
import ReactionButtons from './ReactionButton';
const PostsList = () => { const PostsList = () => {
const posts = useSelector(selectAllPosts); const posts = useSelector(selectAllPosts);
@ -18,6 +19,7 @@ const PostsList = () => {
<PostAuthor userId={post.userId} /> <PostAuthor userId={post.userId} />
<TimeAgo timestamp={post.date} /> <TimeAgo timestamp={post.date} />
</p> </p>
<ReactionButtons post={post} />
</article> </article>
)); ));

View File

@ -0,0 +1,32 @@
import { useDispatch } from 'react-redux';
import { reactionAdded } from './postsSlice';
const reactionEmoji = {
thumbsUp: '👍',
wow: '😮',
heart: '❤️',
rocket: '🚀',
coffee: '☕',
};
const ReactionButtons = ({ post }) => {
const dispatch = useDispatch();
const reactionButtons = Object.entries(reactionEmoji).map(([name, emoji]) => {
return (
<button
key={name}
type="button"
className="reactionButton"
onClick={() =>
dispatch(reactionAdded({ postId: post.id, reaction: name }))
}
>
{emoji} {post.reactions[name]}
</button>
);
});
return <div>{reactionButtons}</div>;
};
export default ReactionButtons;

View File

@ -7,12 +7,26 @@ const initialState = [
title: "Learning Redux Toolkit", title: "Learning Redux Toolkit",
content: "I've heard good things.", content: "I've heard good things.",
date: sub(new Date(), { minutes: 10 }).toISOString(), date: sub(new Date(), { minutes: 10 }).toISOString(),
reactions: {
thumbsUp: 0,
wow: 0,
heart: 0,
rocket: 0,
coffee: 0,
},
}, },
{ {
id: "2", id: "2",
title: "Slice...", title: "Slice...",
content: "The more I say slice, the more I want pizza.", content: "The more I say slice, the more I want pizza.",
date: sub(new Date(), { minutes: 5 }).toISOString(), date: sub(new Date(), { minutes: 5 }).toISOString(),
reactions: {
thumbsUp: 0,
wow: 0,
heart: 0,
rocket: 0,
coffee: 0,
},
}, },
]; ];
@ -33,15 +47,29 @@ const postsSlice = createSlice({
content, content,
userId, userId,
date: new Date().toISOString(), date: new Date().toISOString(),
reactions: {
thumbsUp: 0,
wow: 0,
heart: 0,
rocket: 0,
coffee: 0,
},
}, },
}; };
}, },
}, },
reactionAdded(state, action) {
const { postId, reaction } = action.payload;
const existingPost = state.find((post) => post.id === postId);
if (existingPost) {
existingPost.reactions[reaction]++; // this kind of immer action can only happen in slice
}
},
}, },
}); });
export const selectAllPosts = (state) => state.posts; export const selectAllPosts = (state) => state.posts;
export const { postAdded } = postsSlice.actions; export const { postAdded, reactionAdded } = postsSlice.actions;
export default postsSlice.reducer; export default postsSlice.reducer;