Gourav Thakur
Gourav Thakur

Reputation: 231

Function doesn't return correct state

I am trying to write a function to get a random color from an array COLORS. But, the problem is instead of returning only one color, it is returning too many colors, resulting in an infinite error. Resulting in which react throws Too many re-renders error. What's wrong with my code?

const COLORS = [
  "#FFAEBC",
  "#1ec891",
  "#ff725e",
  "#ffd05b",
  "#A0E7E5",
  "#5885AF",
];

const DisplaySubject = (props) => {

  const [randomColor, setRandomColor] = useState("");

  const generateRandomColor = (colors) => {
    let randColorIndex, randColor;
    for (let i = 0; i < colors.length; i++) {
      randColorIndex = Math.floor(Math.random() * colors.length);
      randColor = colors[randColorIndex];
      return randColor;
    }
    console.log(randColor);
    setRandomColor(randColor);
  };

  generateRandomColor(COLORS);

  console.log("random color state :", randomColor);
  return (
    <div>
      Let's get started
    </div>
  );
};

export default DisplaySubject;

Upvotes: 0

Views: 47

Answers (3)

moonwave99
moonwave99

Reputation: 22817

First, fix your color generator function:

const generateRandomColor = (colors) => {
    const randColorIndex = Math.floor(Math.random() * colors.length);
    return colors[randColorIndex];
};

Then you can use it as the initial value for useState:

const DisplaySubject = (props) => {
    const [randomColor, setRandomColor] = useState(generateRandomColor(COLORS));
    return (
        <div style={{ backgroundColor: randomColor }}>
            Let's get started
        </div>
    );
};

The problem was to call setRandomColor inside the getRandomColor function, that caused an infinite render cycle.

Upvotes: 5

Shakirul Hasan
Shakirul Hasan

Reputation: 678

You don't need to iterate through the array to get a random element. Change your function like this:

  const generateRandomColor = (colors) => {
    let randColorIndex, randColor;
    randColorIndex = Math.floor(Math.random() * colors.length);
    randColor = colors[randColorIndex];
    console.log(randColor);
    setRandomColor(randColor);
    return randColor;
  };

And the function gets called every time the component rerenders. So call the function on an event like onClick or if you want to run the function only once when the component renders for the first time, use useEffect:

useEffect(() => generateRandomColor(COLORS), [])

Upvotes: 2

Dmitriif
Dmitriif

Reputation: 2433

Every time your component mounts, the function generateRandomColor() is called and then it updates the state which causes a new render.

As an option, you can create a button and call this function with onClick event:

<button onClick={generateRandomColor(COLORS)}>generate a color</button>

Upvotes: 1

Related Questions