Home > Software engineering >  How to dynamically add new property while looping through an array using map in reactJs
How to dynamically add new property while looping through an array using map in reactJs

Time:07-03

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>
  )
}

CodePudding user response:

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;
}

CodePudding user response:

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

  • Related