0

I have this array of reactions where every user is allowed to have only one reaction per message:

const reactions = [
  {
    id: "c9c5a273-6033-4239-a6f4-09c067633680",
    profile: {
      first_name: "Pete",
      id: "1",
    },
    reaction_type: "love",
  },
  {
    id: "2e94ee98-7d84-49c5-ac69-600a76d90012",
    profile: {
      first_name: "Eve",
      id: "3",
    },
    reaction_type: "love",
  },
  {
    id: "2e94ee98-7d84-49c5-ac69-600a76d90013",
    profile: {
      first_name: "Brad",
      id: "4",
    },
    reaction_type: "thumbs_up",
  },
  {
    id: "30511fa3-3574-44f4-93f0-04ee35edc62b",
    profile: {
      first_name: "John",
      id: "2",
    },
    reaction_type: "lol",
  },
  {
    id: "30511fa3-3574-44f4-93f0-04ee35edc62b",
    profile: {
      first_name: "Bill",
      id: "5",
    },
    reaction_type: "thumbs_up",
  },
];

Since there could be duplicate reaction_type, I want to keep only "my" reaction, eg. I'm user with id:4 and then remove duplicates of all the other reactions. I don't care witch user will be removed from the array.

Right now I'm using this logic:


const uid = "4";

const uniqueReactions = () => {
  const myReactions = [];
  reactions.forEach((item) => {
    if (item.profile.id === uid) {
      myReactions.push(item);
    }
  });

  if (myReactions.length) {
    const uniques = reactions
      .filter((reaction) => {
        return (
          reaction.reaction_type !== myReactions[0].reaction_type &&
          reaction.profile.id !== uid
        );
      })
      .reduce(
        (r, i) =>
          !r.some(
            (j) => i.reaction_type === j.reaction_type && i.profile.id !== uid
          )
            ? [...r, i]
            : r,
        []
      );
    return [...myReactions, ...uniques];
  } else {
    return reactions.reduce(
      (r, i) =>
        !r.some((j) => i.reaction_type === j.reaction_type) ? [...r, i] : r,
      []
    );
  }
};

Is there a better way on handling this? It feels messy and noisy.

Edit: just for clarity, I want to keep "my" reaction so I can highlight it with a different color in the UI.

6
  • What happens in case user '4' (the OP) appears more than just once within the reaction items with another reaction_type than just 'thumbs_up'? Should all other reaction items be ignored likewise? Commented May 26, 2022 at 12:33
  • @PeterSeliger users are allowed to only have one reaction per message Commented May 26, 2022 at 12:34
  • Got it, and a message then gets identified by an reaction item's id value? Commented May 26, 2022 at 12:36
  • Above the message i represent the reaction_type, so if a message has 10 love and 5 thumb_up it will only show 1 heart and 1 thumb up icon. Hope this covers what you asked. Edit: my reaction will be highlighted in a different color than the others. Commented May 26, 2022 at 12:38
  • 1
    You're right, the duplicate reaction slipped in from my tests, will edit the question. Every reaction has a message_id. Commented May 26, 2022 at 12:44

1 Answer 1

1

I think what mostly makes it messy is the abundant use of ternary and one letter variable names.

That said, I think it could be simpler. Here's my attempt at it:

function getUniqueReactions(id, reactions) {
    const userTypes = reactions
        .filter(reaction => reaction.profile.id === id)
        .map(reaction => reaction.reaction_type);
    const processedTypes = [];
    
    return reactions.reduce((accumulator, curItem) => {
        const { reaction_type: curType } = curItem; // The current type
        
        // If the current user has posted this type but this isn't the current user, skip the item
        if (userTypes.includes(curType) && curItem.profile.id !== id) {
            return accumulator;
        }
        
        // Check if either we're the supplied user and the type matches
        // or this is a reaction type the user hasn't posted and we haven't seen yet
        if (curItem.profile.id === id || !processedTypes.includes(curType)) {
            accumulator.push(curItem);
            processedTypes.push(curType);
        }
        
        return accumulator;
    }, []);
}

console.log(getUniqueReactions("4", reactions));
Sign up to request clarification or add additional context in comments.

Comments

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.