Home > Back-end >  change the text color based on a state
change the text color based on a state

Time:08-15

I am having a problem changing the text color based on either the element has negative value or positive one.

I have an array with data, containing negative/positive values of each user's balance (fake data ofc).

data.js

export const users = [
  {
    id: 0,
    username: "CryptoFunks",
    emailAddress: "[email protected]",
    balanceRate:  26.52,
    balance: "19,769.39",
    avatar: cryptoFunksAvatar,
    verified: true,
  },
  {
    id: 1,
    username: "Cryptix",
    emailAddress: "[email protected]",
    balanceRate: -10.52,
    balance: "2,769.39",
    avatar: cryptixAvatar,
    verified: false,
  },
  {
    id: 2,
    username: "Frensware",
    emailAddress: "[email protected]",
    balanceRate:  2.52,
    balance: "9,232.39",
    avatar: frenswareAvatar,
    verified: false,
  },
  {
    id: 3,
    username: "PunkArt",
    emailAddress: "[email protected]",
    balanceRate:  1.52,
    balance: "3,769.39",
    avatar: punkArtAvatar,
    verified: true,
  },
  {
    id: 4,
    username: "Art Crypto",
    emailAddress: "[email protected]",
    balanceRate: -2.52,
    balance: "10,769.39",
    avatar: artCryptoAvatar,
    verified: false,
  },
];

And here's what I am trying to do with it.

TopCollections.jsx

import React, { useEffect, useState } from "react";

import { users } from "../../public/data/data";

const TopCollections = () => {
  const [isNegative, setIsNegative] = useState(false);

  useEffect(() => {
    users.forEach((element) => {
      if (element.balanceRate < 0) {
        setIsNegative(true);
      } else if (element.balanceRate > 0) {
        setIsNegative(false);
      }
    });
  });

  return (
    <section>
      <div className="container max-w-[1216px] mx-auto px-4">
        <div>
          <h3>Top collections over</h3>
          <p>Last 7 days</p>
          <ul>
            {users.map((item, index) => {
              return (
                // item
                <li key={index}>
                  {/* index */}
                  <span>{index   1}</span>
                  {/* avatar */}
                  <img src={item.avatar} />
                  {/* username & balance */}
                  <div>
                    <p>{item.username}</p>
                    <p>{item.balance}</p>
                  </div>
                  {/* balance rate */}
                  <span
                    className={`${
                      isNegative ? "text-[#FF002E]" : "text-[#14C8B0]"
                    }`}
                  >
                    {item.balanceRate}%
                  </span>
                </li>
              );
            })}
          </ul>
        </div>
      </div>
    </section>
  );
};

export default TopCollections;

Implementation is awful, sorry for that, I am pretty new to this, however I was trying to figure out how to determine whether the value is negative or positive. I tried to do forEach() function for each element of the array and it seems to be working fine if I check with console.log(); it actually defines numbers with negative & positive values. The main problem is that it does not change color based on state, that I specified. I feel like there is a dumb newbie issue which I do not see point blank, but still.

CodePudding user response:

You don't need a state here. isNegative is a (computable) property of each user user.balanceRate < 0 and it's so simple to compute that you don't need to store it anywhere.

const TopCollections = () => {
  return (
    <section>
      <div className="container max-w-[1216px] mx-auto px-4">
        <div>
          <h3>Top collections over</h3>
          <p>Last 7 days</p>
          <ul>
            {users.map((item, index) => {
              return (
                // item
                <li key={item.id}>
                  {/* index */}
                  <span>{index   1}</span>
                  {/* avatar */}
                  <img src={item.avatar} />
                  {/* username & balance */}
                  <div>
                    <p>{item.username}</p>
                    <p>{item.balance}</p>
                  </div>
                  {/* balance rate */}
                  <span
                    className={
                      item.balanceRate<0 ? "text-[#FF002E]" : "text-[#14C8B0]"
                    }
                  >
                    {item.balanceRate}%
                  </span>
                </li>
              );
            })}
          </ul>
        </div>
      </div>
    </section>
  );
};

CodePudding user response:

there a couple of problems with the code you shared.

I think you misunderstand how useState and useEffect work and how they are used. Also, in the future I would say to you should avoid using forEach at all costs as you will mutate your data and that can cause problems that are hard to debug down the road.

To be honest I don't think you need either hooks to solve your problem, you already have all the data you need in the users array. You just need to define the Boolean in the map statement you already have in your code. So you can remove those hooks and just add the following const to your map statement to figure out which user has a negative balance:

{users.map((item, index) => {
  const isNegative = item.balanceRate < 0;
  return (
    ...
  )
  • Related