0

Basically I was trying to make 10*10 grid such that clicking on specific cell by it cell number change all multiple cell color? for example clicking on cell 5 it change all boxes which having multiple of 5 values. For grid I used tailwindcss

enter image description here

Can anyone please tell that why in my code background color of multiple cells is not changing?

const { useState } = React;

function App() {
  const [fillcolor, setFillcolor] = useState("");
  var items = [];
  for (let i = 1; i <= 100; i++) {
    items.push(<div onClick={() => changeColor(i)} className="border border-gray-600 text-center">
      {i}
    </div>)
  }
  function changeColor(index) {
    alert(index);
    setFillcolor("yellow");
    for (var i = 0; i < items.length; i++) {
      if ((i + 1) % index === 0) {
        items[i] = <div style={{ backgroundColor: fillcolor }} className="border border-gray-600 text-center">
          {(i + 1)}
        </div>
      }
    }
    console.log(items[0]);
  }
  return (
    <div className="App">
      <div className="container">
        <div className="grid grid-cols-10 grid-rows-10">
          {items}
        </div>
      </div>
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
<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="root"></div>
Giovanni Esposito
  • 10,696
  • 1
  • 14
  • 30
Suyash
  • 29
  • 7
  • 1
    Keep `Item` as a state, do not handle DOM manipulations yourself if you are using react. Keep things you want to change as states and update them through their dispatchers. – Imanpal Singh Jul 23 '21 at 14:50

2 Answers2

0

You are modifying items inside your changeColor function, which React will never find out (since it's not a state). When React rerenders the component, the variable will be redefined. Instead, I'd recommend storing the highlighted factor. The fillColor does not need to change (at least in your code it's always set to 'yellow') and therefore should not be a state.

The following should work:

function App() {
  const [selectedIndex, setSelectedIndex] = useState(null);
  const items = [];
  for (let i = 1; i <= 100; i++) {
    let style = {};
    if(selectedIndex !== null && i % selectedIndex === 0){
        style = {
            backgroundColor: "yellow"
        };
    }
    items.push(<div onClick={() => changeColor(i)} className="border border-gray-600 text-center" style={style}>
      {i}
    </div>)
  }
  function changeColor(index) {
    // only need to set the state here
    setSelectedIndex(index);
  }
  return (
    <div className="App">
      <div className="container">
        <div className="grid grid-cols-10 grid-rows-10">
          {items}
        </div>
      </div>
    </div>
  );
}
Taxel
  • 3,859
  • 1
  • 18
  • 40
0

As @skrrrt said, in React is suggested to not manipulate DOM like you are doing now. Much better use state variables. I suggest you to modify your code in this way:

const { useState } = React;

function App() {
  const [fillcolor, setFillcolor] = useState(new Array(100).fill("white"));  // <-- this is an array of colors to apply to elements

  const numbers = Array.from({length: 100}, (_, i) => i + 1); // <-- this is an array of first 100 numbers from 1 to 100

  const multiplesOf = (numbers, number) => numbers.filter(n => !(n % number));  // <-- this function returns multiple of selected value in numbers array

  function changeColor(index) {
 let result = [...fillcolor];
 let indexToColor = multiplesOf(numbers, index);
 indexToColor.forEach((idx) => result[idx - 1] = "yellow");
 setFillcolor(result);
 
  }

  return (
<div className="App">
  <div className="container">
    <div className="grid grid-cols-10 grid-rows-10">
      {numbers.map((el) => (
         <div style={{ backgroundColor: fillcolor[el - 1] }} onClick={() => changeColor(el)} className="border border-gray-600 text-center">
         {el}
         </div>
      ))}
    </div>
  </div>
</div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
<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="root"></div>

Credits: multiplesOf function is taken from here; numbers fill function is taken from here.

Giovanni Esposito
  • 10,696
  • 1
  • 14
  • 30