From 225fcfa26aeb10792969e66f499904357f6b4a38 Mon Sep 17 00:00:00 2001 From: Kim Anh Nguyen <4783194+kimanhou@users.noreply.github.com> Date: Tue, 14 Oct 2025 10:32:37 +0200 Subject: [PATCH] Refactor reaction_list.tsx Signed-off-by: Kim Anh Nguyen <4783194+kimanhou@users.noreply.github.com> --- .../post_view/reaction_list/reaction_list.tsx | 124 ++++++++---------- 1 file changed, 54 insertions(+), 70 deletions(-) diff --git a/webapp/channels/src/components/post_view/reaction_list/reaction_list.tsx b/webapp/channels/src/components/post_view/reaction_list/reaction_list.tsx index 2c9b5872739..7f8afb467c0 100644 --- a/webapp/channels/src/components/post_view/reaction_list/reaction_list.tsx +++ b/webapp/channels/src/components/post_view/reaction_list/reaction_list.tsx @@ -1,7 +1,8 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React from 'react'; +import React, {useMemo, useCallback} from 'react'; +import {useIntl} from 'react-intl'; import type {Emoji} from '@mattermost/types/emojis'; import type {Post} from '@mattermost/types/posts'; @@ -11,8 +12,6 @@ import {getEmojiName} from 'mattermost-redux/utils/emoji_utils'; import Reaction from 'components/post_view/reaction'; -import {localizeMessage} from 'utils/utils'; - import AddReactionButton from './add_reaction_button'; type Props = { @@ -46,88 +45,73 @@ type Props = { }; }; -type State = { - emojiNames: string[]; -}; +const ReactionList: React.FC = ({post, teamId, reactions: reactionMap, canAddReactions, actions}) => { + const intl = useIntl(); -export default class ReactionList extends React.PureComponent { - constructor(props: Props) { - super(props); - - this.state = { - emojiNames: [], - }; - } - - static getDerivedStateFromProps(props: Props, state: State): Partial | null { - let emojiNames = state.emojiNames; - - for (const {emoji_name: emojiName} of Object.values(props.reactions ?? {})) { - if (!emojiNames.includes(emojiName)) { - emojiNames = [...emojiNames, emojiName]; - } + const emojiNames = useMemo(() => { + if (!reactionMap) { + return []; } - return (emojiNames === state.emojiNames) ? null : {emojiNames}; - } + const names = Object.values(reactionMap).map((r) => r.emoji_name); + return [...new Set(names)]; + }, [reactionMap]); - handleEmojiClick = (emoji: Emoji): void => { + const handleEmojiClick = useCallback((emoji: Emoji): void => { const emojiName = getEmojiName(emoji); - this.props.actions.toggleReaction(this.props.post.id, emojiName); - }; + actions.toggleReaction(post.id, emojiName); + }, [post.id, actions.toggleReaction]); - render(): React.ReactNode { - const reactionsByName = new Map(); - - if (this.props.reactions) { - for (const reaction of Object.values(this.props.reactions)) { + const reactionsByName = useMemo(() => { + const map = new Map(); + if (reactionMap) { + for (const reaction of Object.values(reactionMap)) { const emojiName = reaction.emoji_name; - if (reactionsByName.has(emojiName)) { - reactionsByName.get(emojiName).push(reaction); + if (map.has(emojiName)) { + map.get(emojiName)!.push(reaction); } else { - reactionsByName.set(emojiName, [reaction]); + map.set(emojiName, [reaction]); } } } + return map; + }, [reactionMap]); - if (reactionsByName.size === 0) { - return null; - } + if (reactionsByName.size === 0) { + return null; + } - const reactions = this.state.emojiNames.map((emojiName) => { - if (reactionsByName.has(emojiName)) { - return ( - - ); - } - return null; - }); - - let addReaction = null; - if (this.props.canAddReactions) { - addReaction = ( - { + if (reactionsByName.has(emojiName)) { + return ( + ); } + return null; + }); - return ( -
- {reactions} - {addReaction} -
- ); - } -} + return ( +
+ {reactionComponents} + {canAddReactions && ( + + )} +
+ ); +}; + +export default ReactionList;