2

I am still in the midst of learning React and Javascript and have came to a roadblock with my current project.

Project goal I am trying to map through two array of objects, and check if a certain property matches. if recommendedSkillTree.skills.skill === currentSkills.skill, I would then like to check if recommendedSkillTree.skills.level > currentSkills.level. if the above condition matches, or if currentSkills.skill do not have the skills in the recommendedSkillTree Data, the skill will then show up in a red text. Else, green text.

What I have done I have tried mapping between the 2 arrays to check if currentSkills.skill === recommendedSkillTree.skills.skill.

  const skillMatch = recommendedSkillTree.filter((skillRecommended) =>
    currentSkills.some((skillCurrent) => skillRecommended.skills.skill === skillCurrent.skill)
  );
.
.
.
  return (
   <div>
     {recommendedSkillTree.map((item, i) => (
            <div key={item.id}>
              <div
                style={{
                  color: !skillMatch[i] ? "red" : "green", 
                }}
              >
                {item.skill}
              </div>
            </div>
          ))}
   </div>


By doing so, I am able to churn out an output where skills that are present in currentSkills are shown in green, and those that are not in it are shown in red.

Next I would like to go one step deeper, and tried to compare the skill level of the present skills, and if they fall short of the recommended level, the text would then show in red.

  const levelGap = recommendedSkillTree.map((recommendedLevel) =>
    currentSkills.some((levelCurrent) => recommendedLevel.level > levelCurrent.level)
  );

By doing so, I would be expecting an output of

[true, false, true, true, true, true, true, true, true]

instead I've got:

[true, true, true, true, false, true, true, false, false]

I am unable to see which part have went wrong. Would greatly appreciate if any seniors in this field would guide me along.

Data 1

const recommendedSkillTree = [
  {
    id: "1",
    role: "Paladin",
    skills: [
      {
        id: "1",
        skill: "Attack",
        level: "3",
      },
      {
        id: "2",
        skill: "Block",
        level: "3",
      },
      {
        id: "3",
        skill: "Taunt",
        level: "3",
      },
      {
        id: "4",
        skill: "Heal",
        level: "4",
      },
      {
        id: "5",
        skill: "Group Heal",
        level: "2",
      },
      {
        id: "6",
        skill: "Double Attack",
        level: "4",
      },
      {
        id: "7",
        skill: "Ultimate",
        level: "3",
      },
      {
        id: "8",
        skill: "Defense Up",
        level: "2",
      },
      {
        id: "9",
        skill: "Attack Up",
        level: "2",
      },
    ],
  },
];
export default recommendedSkillTree;

Data 2

const currentSkills = [
  {
    id: "1",
    skill: "Attack",
    level: "2",
  },
  {
    id: "2",
    skill: "Block",
    level: "3",
  },
  {
    id: "3",
    skill: "Taunt",
    level: "2",
  },
  {
    id: "4",
    skill: "Heal",
    level: "3",
  },
  {
    id: "5",
    skill: "Final Slash",
    level: "3",
  },
];
export default currentSkills;

Thank you in advance for your time, and I do apologize if my way of asking questions are not up to community standard as this is my first time posting on here. I do not really have anyone around me to ask questions on since I am fully self-taught and no one around me is in the tech field. Thank you so much.

3
  • 1
    I think it's because you're not looking at the same skills. In the first filter function you have skillRecommended.skill === skillCurrent.skill - so it matches the skill in recommended with that in current. You don't do that in levelGap calculation so I guess it's just looking at any old skill without making sure that the recommended and current skills are the same skill. Try recommendedLevel.skill === levelCurrent.skill && recommendedLevel.level > levelCurrent.level Commented Mar 21, 2022 at 19:06
  • Hi @James , thank you for the reply. I may have accidentally left it out while typing my code in. I have edited my post to include it in. Commented Mar 21, 2022 at 19:19
  • 1
    In this code: ` {recommendedSkillTree.map((item, i) => (<div key={item.id}>...{item.skill}..., one tries to .map` over the outer-array (with role: Paladin) while also trying to render {item.skill} which is not present in the outer-object. Commented Mar 21, 2022 at 21:00

2 Answers 2

1

This may be one possible solution to achieve the desired objective.

Code Snippet

const isGreenOrRed = (reco, curr) => (
  reco.skills.map(re => (
    curr.some(({skill}) => skill === re.skill)
    ? curr.find(({skill}) => skill === re.skill)['level'] >= re.level
      ? 'green'
      : 'red'
    : 'red' 
  ))
);

const recommendedSkillTree = [
  {
    id: "1",
    role: "Paladin",
    skills: [
      {
        id: "1",
        skill: "Attack",
        level: "3",
      },
      {
        id: "2",
        skill: "Block",
        level: "3",
      },
      {
        id: "3",
        skill: "Taunt",
        level: "3",
      },
      {
        id: "4",
        skill: "Heal",
        level: "4",
      },
      {
        id: "5",
        skill: "Group Heal",
        level: "2",
      },
      {
        id: "6",
        skill: "Double Attack",
        level: "4",
      },
      {
        id: "7",
        skill: "Ultimate",
        level: "3",
      },
      {
        id: "8",
        skill: "Defense Up",
        level: "2",
      },
      {
        id: "9",
        skill: "Attack Up",
        level: "2",
      },
    ],
  },
];

const currentSkills = [
  {
    id: "1",
    skill: "Attack",
    level: "2",
  },
  {
    id: "2",
    skill: "Block",
    level: "3",
  },
  {
    id: "3",
    skill: "Taunt",
    level: "2",
  },
  {
    id: "4",
    skill: "Heal",
    level: "3",
  },
  {
    id: "5",
    skill: "Final Slash",
    level: "3",
  },
];

console.log(isGreenOrRed(recommendedSkillTree[0], currentSkills).join(", "));

const SomeComp = ({getColor, ...props}) => (
   <div>
     {recommendedSkillTree[0].skills.map((item, i) => (
            <div key={item.id}>
              <div
                style={{
                  color: getColor[i] 
                }}
              >
                {item.skill}
              </div>
            </div>
          ))}
   </div>
);

ReactDOM.render(
  <div>
    <h4>Demo UI</h4>
    <SomeComp getColor={isGreenOrRed(recommendedSkillTree[0], currentSkills)}/>
  </div>,
  document.getElementById('rd')
);
<div id="rd" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>

Explanation

  • this uses the same logic as attempted by OP in the question
  • fixes some of the issues faced

Below solution employs an alternative approach to get the same result.

Code Snippet

const isGreenOrRed = (needle, haystack) => (
    haystack.some(({skill}) => skill === needle.skill)
    ? haystack.find(({skill}) => skill === needle.skill)['level'] >= needle.level
      ? 'green'
      : 'red'
    : 'red' 
);

const recommendedSkillTree = [
  {
    id: "1",
    role: "Paladin",
    skills: [
      {
        id: "1",
        skill: "Attack",
        level: "3",
      },
      {
        id: "2",
        skill: "Block",
        level: "3",
      },
      {
        id: "3",
        skill: "Taunt",
        level: "3",
      },
      {
        id: "4",
        skill: "Heal",
        level: "4",
      },
      {
        id: "5",
        skill: "Group Heal",
        level: "2",
      },
      {
        id: "6",
        skill: "Double Attack",
        level: "4",
      },
      {
        id: "7",
        skill: "Ultimate",
        level: "3",
      },
      {
        id: "8",
        skill: "Defense Up",
        level: "2",
      },
      {
        id: "9",
        skill: "Attack Up",
        level: "2",
      },
    ],
  },
];

const currentSkills = [
  {
    id: "1",
    skill: "Attack",
    level: "2",
  },
  {
    id: "2",
    skill: "Block",
    level: "3",
  },
  {
    id: "3",
    skill: "Taunt",
    level: "2",
  },
  {
    id: "4",
    skill: "Heal",
    level: "3",
  },
  {
    id: "5",
    skill: "Final Slash",
    level: "3",
  },
];

console.log(recommendedSkillTree[0].skills.map(it => isGreenOrRed(it, currentSkills)).join(", "));

const SomeComp = () => (
   <div>
     {recommendedSkillTree[0].skills.map(item => (
            <div key={item.id}>
              <div
                style={{
                  color: isGreenOrRed(item, currentSkills)
                }}
              >
                {item.skill}
              </div>
            </div>
          ))}
   </div>
);

ReactDOM.render(
  <div>
    <h4>Demo UI - Alternate Approach</h4>
    <SomeComp />
  </div>,
  document.getElementById('rd')
);
<div id="rd" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>

Explanation

  • This pushes the validation at the individual skill object level
  • Thus, re-using the existing .map iteration happening in the JSX
Sign up to request clarification or add additional context in comments.

Comments

1

Here's an example using Lodash map. You can try play around with the check function to get the desired result.

const recommendedSkillTree = [{
  id: "1",
  role: "Paladin",
  skills: [{
      id: "1",
      skill: "Attack",
      level: "3",
    },
    {
      id: "2",
      skill: "Block",
      level: "3",
    },
    {
      id: "3",
      skill: "Taunt",
      level: "3",
    },
    {
      id: "4",
      skill: "Heal",
      level: "4",
    },
    {
      id: "5",
      skill: "Group Heal",
      level: "2",
    },
    {
      id: "6",
      skill: "Double Attack",
      level: "4",
    },
    {
      id: "7",
      skill: "Ultimate",
      level: "3",
    },
    {
      id: "8",
      skill: "Defense Up",
      level: "2",
    },
    {
      id: "9",
      skill: "Attack Up",
      level: "2",
    },
  ],
}];

const currentSkills = [{
    id: "1",
    skill: "Attack",
    level: "2",
  },
  {
    id: "2",
    skill: "Block",
    level: "3",
  },
  {
    id: "3",
    skill: "Taunt",
    level: "2",
  },
  {
    id: "4",
    skill: "Heal",
    level: "3",
  },
  {
    id: "5",
    skill: "Final Slash",
    level: "3",
  },
];

var result = [];

function check(skill) {
  var found = _.find(currentSkills, function(o) {
    return o.skill === skill.skill;
  });

  if (found) {
    result.push(found.level >= skill.level);
  } else {
    result.push(false);
  }
}

_.map(recommendedSkillTree[0].skills, check);

console.log(result);
<script src="https://lodash.com/vendor/cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

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.