Vardan Hambardzumyan
Vardan Hambardzumyan

Reputation: 277

bug from element showing

Hi all I have following code: my code

In code I am recieving data from backend, In my case I hardcoded that part (see below data)

    const skills = [
     {
       id: 1,
       name: "Html "
     },
     { id: 2, name: "CSS" },
     { id: 3, name: "Scss" },
     { id: 4, name: "Bootstrap 4" },
     { id: 5, name: "JavaScript" },
     { id: 6, name: "Jquery" },
     { id: 7, name: "React JS" },
     { id: 8, name: "Angular " },
     { id: 9, name: "Vue.js " },
     { id: 10, name: "SQL" },
     { id: 11, name: "php" },
     { id: 12, name: "Laravel" }
    ];

I am counting all my skill names char length and if that length is greater then allowCharCount I am hiding all rest skills and showing in number how many skills is hided. That part is working.

   let lengthCount = 0;
   let maxIndex = 0;
   const allowCharCount = 20;
   const skill = [];

   export const Skill = ({ data }) => {
     if (data === undefined) {
        return null;
      } else {
        data.map((item) => {
          if (lengthCount <= allowCharCount) {
            maxIndex = item.id;
            skill.push(item);
          }
          lengthCount += item.name.length;
        });

        const mySkills = skill.map((perSkill) => (
          <span key={perSkill.id} className="skillItem">
            {perSkill.name}
         </span>
        ));

        return (
          <div className="skillWrapper">
            <div>{mySkills}</div>
            {lengthCount > allowCharCount ? (
              <div className="skillNumber">+{data.length - maxIndex}</div>
            ) : null}
          </div>
        );
      }
    };

but when my chars count is less then allowCharCount it's not working.

If I only have first 3 items (Html, CSS, Scss) I see following view

Html CSS Scss Html CSS Scss +0.

Please help me to fix this code for that case (if chars count is less than allowCharCount) I need to show only correct items with no any +0 count

Upvotes: 0

Views: 42

Answers (1)

Mikhail Grechka
Mikhail Grechka

Reputation: 735

You should rethink the way you write the component and code in general

  • You have to store dynamic variables inside the component
  • To save the result of array operations, you should either mutate state or create a new variable inside the component (which is more preferable in your case).
  • .map method return an array of values returned by callback inside of it. If you're not going to return anything, use .forEach instead
  • Use .length property instead of incrementing the size of array by yourself to avoid bugs.

The reason why you get duplicated elements is that you don't clear the array before the component updates, so the algorithm just pushes these values again.

Working code example:

export const Skill = ({ data }) => {
  // here I invert condition to get the rest code out of brackets
  if (!data) return null;

  // all of the dynamic data should be inside the component
  const failIndex = React.useMemo(() => {
    let charCount = 0;

    for (let i = 0; i < data.length; i++) {
      charCount += data[i].name.length;
      if (charCount > allowCharCount) return i;
    }

    return -1;
  }, [data]);

  // check if data has element that doesn't pass the condition
  const dataBeforeFail = failIndex === -1 ? data : data.slice(0, failIndex + 1);

  const hiddenSkillsCount = data.length - dataBeforeFail.length;

  return (
    <div className="skillWrapper">
      <div>
        {dataBeforeFail.map((perSkill) => (
          <span key={perSkill.id} className="skillItem">
            {perSkill.name}
          </span>
        ))}
      </div>
      {hiddenSkillsCount > 0 && (
        <div className="skillNumber">+{hiddenSkillsCount}</div>
      )}
    </div>
  );
};

Upvotes: 2

Related Questions