You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJs中使用map遍历数组时如何动态添加表情计数属性

React表情组件渲染Firebase对应计数实现方案

现有代码结构

本地默认表情常量配置

本地通过SVG组件引入预设表情,导出表情选项数组:

import { ReactComponent as Coin } from "../assets/emojiIcons/coin.svg"
import { ReactComponent as Rocket } from "../assets/emojiIcons/rocket.svg"

const DEFAULT_EMOJI_OPTIONS = [
  {
    emoji: Rocket,
    label: "rocket",
  },
  {
    emoji: Coin,
    label: "coin",
  },
]

export { DEFAULT_EMOJI_OPTIONS }

Firebase返回的反应数据结构

接口返回的reactions数组存储每个表情的标签、计数、触发用户列表,结构如下:

reactions: [
  {
    "emoji": "rocket",
    "label": "rocket",
    "count": 23,
    "users": [
      "3322424",
      "3243242"
     ]
  },
  {...},
  {...}
]

待完善的组件初始代码

需要在遍历默认表情的逻辑中,插入对应表情的实时计数:

import { DEFAULT_EMOJI_OPTIONS } from "../../utils/emojis"

const EmojiSection = ({reactions}) => {

  return (
    <div className="text-white border-2 border-gray-800 rounded p-3 my-8 max-w-xs mx-auto">
          {DEFAULT_EMOJI_OPTIONS.map((emoji) => (
        <span
          key={emoji.label}
          onClick={() => console.log("clicked")}
        >
          <emoji.emoji width={32} height={32} />
          <span>
            {ADD EMOJI COUNT FROM FIREBASE}
          </span>
        </span>
      ))}
    </div>
  )
}

实现方法

核心逻辑是通过两个数组共有的label字段做匹配,遍历本地默认表情时,从reactions数组中找到对应项取count值,未匹配到对应表情时默认显示0。

基础实现版本

直接在map循环中做匹配,适合表情数量较少的场景:

import { DEFAULT_EMOJI_OPTIONS } from "../../utils/emojis"

const EmojiSection = ({reactions}) => {
  return (
    <div className="text-white border-2 border-gray-800 rounded p-3 my-8 max-w-xs mx-auto">
      {DEFAULT_EMOJI_OPTIONS.map((emoji) => {
        // 用label匹配当前表情对应的Firebase反应数据
        const matchedReaction = reactions.find(item => item.label === emoji.label)
        const count = matchedReaction?.count ?? 0
        return (
          <span
            key={emoji.label}
            onClick={() => console.log("clicked")}
            className="inline-flex items-center gap-1 cursor-pointer mr-2"
          >
            <emoji.emoji width={32} height={32} />
            <span>{count}</span>
          </span>
        )
      })}
    </div>
  )
}

如果项目构建配置不支持可选链(?.)和空值合并运算符(??),把取值逻辑替换为const count = matchedReaction ? matchedReaction.count : 0即可。代码中新增的inline-flex等样式类是为了让表情和数字排版对齐,不需要可以直接删除。

性能优化版本

如果表情选项较多,每次遍历都执行find会产生重复计算,可以提前把reactions数组转换为以label为键的映射对象,把查询复杂度从O(n)降到O(1):

import { useMemo } from "react"
import { DEFAULT_EMOJI_OPTIONS } from "../../utils/emojis"

const EmojiSection = ({reactions}) => {
  // 仅当reactions数据变化时,重新构建映射表
  const reactionMap = useMemo(() => {
    const map = {}
    reactions?.forEach(item => {
      map[item.label] = item
    })
    return map
  }, [reactions])

  return (
    <div className="text-white border-2 border-gray-800 rounded p-3 my-8 max-w-xs mx-auto">
      {DEFAULT_EMOJI_OPTIONS.map((emoji) => {
        const count = reactionMap[emoji.label]?.count ?? 0
        return (
          <span
            key={emoji.label}
            onClick={() => console.log("clicked")}
            className="inline-flex items-center gap-1 cursor-pointer mr-2"
          >
            <emoji.emoji width={32} height={32} />
            <span>{count}</span>
          </span>
        )
      })}
    </div>
  )
}

内容的提问来源于stack exchange,提问作者r121

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 03:20:03