1

I have an emoji component in which I loop through an array of emojis (SVG's) that's stored like this:

Constant Emojis Array:

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 }

and I'm also getting emoji count from the reactions array(it's coming from firebase). The reactions array looks like this:

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

I would like to know how to add an emoji count that I'm getting from firebase inside a map in the below code?

Emoji component:

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>
  )
}
2
  • Do you want to list the counts of all reactions, or just rocket and coin? Commented Jul 2, 2022 at 6:57
  • I have total of 9 emojis and I want to load these 9 from DEFAULT_EMOJI_OPTIONS and then add the corresponding count to each emoji from firebase. Commented Jul 2, 2022 at 7:01

2 Answers 2

1

You can archive your goal by this.

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>
            {reactions.find(reaction => reaction.label === emoji.label)?.count}
          </span>
        </span>
      ))}
    </div>
  )
}

And if you want to increase click count per user, it can be implemented by using useState(), assuming that 'reactions' value is just used in this component and no need to share user clicks count information in other components.

Else, if you have got some update method relates to firebase, you have to include that method instead of useState.

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

const EmojiSection = ({reactions}) => {
  const [userReactions, setUserReactions] = useState(reactions);

//Assuming that you can get user id from custom context-UserContext
  const {user} = useContext(UserContext);
  const {userId} = user;
  
  const handleClick = label => {
    let reaction = userReactions.find(r=>r.label==label);
    if(!reaction) return;
    if(userReactions.users.include(userId)){
       setUserReactions({
          ...userReactions,
          count: userReactions.count-1,
          user: removeValue(userReactions.user, userId)
       });
    }else{
       setUserReactions({
          ...userReactions,
          count: userReactions.count+1,
          user: addValue(userReactions.user, userId)
       });

       
    }

  };
  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={() => handleClick(emoji.label)}
        >
          <emoji.emoji width={32} height={32} />
          <span>
            {reactions.find(reaction => reaction.label === emoji.label)?.count}
          </span>
        </span>
      ))}
    </div>
  )
}

const removeValue = (array, item) => {
    var index = array.indexOf(item);
    if (index !== -1) {
    array.splice(index, 1);
    }
    return array;
}
const addValue = (array, item) => {
   array.push(item);
   return array;
}
Sign up to request clarification or add additional context in comments.

4 Comments

thanks for the great answer. In my case reactions is an array of reaction. Something like this: ``` reactions: [ { "emoji": "rocket", "label": "rocket", "count": 23, "users": [ "3322424", "3243242" ] }, { "emoji": "coin", "label": "coin", "count": 43, "users": [ "332242df4", "32432sfs42" ] }, {...} ] ```
It does not represent reactions given by a single user. It represents all reactions associated with a single post. Please check array of reaction in the question
I have one more question Is there any better way to structure this data?
thanks. I think it'd be better if you can structure this data as two arrays. first as reactions[{emoji:'rocket', label:'rocket', count:23}...] and second as reactions_user:[{emoji:'rocket', users:['32405',..]}] or user_reactions:['32048':['rocket', 'coin',...]]
1

You can find the count value by the common prop label doing:

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={() => null}
        >
          <emoji.emoji width={32} height={32} />
          <span>
            {reactions.find(reaction => reaction.label === emoji.label).count}
          </span>
        </span>
      ))}
    </div>
  )
}

Also I don't get the point of using 2 nested maps btw maybe you can throw some light on this :D

1 Comment

Thanks for your answer. I mistakenly added two maps. really sorry for that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.