How to use useState hook for a randomizing array problem(React useState)?

Viewed 554

I'm trying to figure out how to solve a color boxes exercise that applies useState hook concept. Given an array that contains 12 different unique colors, initially the state will show 12 divs with a corresponding color. Upon clicking the button, only randomly chosen div will change to a random color(out of the 12 given colors) as well as flagging that div with the message "changed" on the div. So far I was able to make the color box container showing each color on a div. I see the state is changing to a random color every time when I click. But I don't know how to make only that random div to change the color and show the message. Does this problem require a unique id for each color for tracking change of the state?

import React, { useState } from 'react';
import ColorBox from './ColorBox';
import {choice} from './colorHelpers';


const ColorBoxes = () => {
   
    const [ boxes, setBoxes] = useState(colors);
    
    const [msg, setMsg] = useState(null);
        
    const clickHandler = () => {
        setBoxes(()=>choice(colors));
        setMsg('changed');    
    };
        

    return (
    <>  
        {colors.map((color,i) =>{
            return(
            <div>
               <ColorBox key={i} color={color} />{color} 
            </div>
            );
        })} 
        <button onClick={clickHandler}>Change Color!</button>    
    </>
    );

};

import React from 'react';
import './ColorBox.css';

const ColorBox = ({ color }) => {
    return <div className="colorBox" style={{ backgroundColor: color }} />;
};

export default ColorBox;


const choice = (arr) => {
    const randIdx = Math.floor(Math.random() * arr.length);
    return arr[randIdx];
};

export { choice };

1 Answers

You should save your initial color inside useState , then change color for random index with useState, check this example:

const colors = [
  "#8391B5",
  "#290D11",
  "#0C9ABC",
  "#0E17F4",
  "#97BC89",
  "#6B48F7",
  "#584A35",
  "#669F15",
  "#15FC93",
  "#7C8329",
  "#27D792",
  "#4786C8",
];

const ColorBoxes = () => {
  const [boxes, setBoxes] = React.useState(
    colors.sort(() => Math.random() - 0.5)
  );
  const [msg, setMsg] = React.useState(Array.from(Array(12)));

  const clickHandler = (index) => {
    const randomColor = colors[Math.floor(Math.random() * 12)];
    setBoxes((prev) => prev.map((x, i) => (i === index ? randomColor : x)));
    setMsg((prev) => prev.map((x, i) => (i === index ? "changed!" : x)));
  };

  return (
    <React.Fragment>
      {boxes.map((color, i) => (
        <ColorBox key={i + color} color={color} msg={msg[i]} />
      ))}
      <button onClick={() => clickHandler(Math.floor(Math.random() * 12))}>
        Change Color!
      </button>
    </React.Fragment>
  );
}
const ColorBox = ({ color, msg }) => (
  <div className="colorBox" style={{ backgroundColor: color }}>
    {color} {msg}
  </div>
);

ReactDOM.render(
  <ColorBoxes />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Related