Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

REACT : getting error while re-rendering components using setState hook

I’m trying to change an inline style property of several items that have position info stored in a useState hook as well on the style property of each item rendered. I wanted to change the CSS value of all the items except the one I clicked on. I devised a function to do so, however when I try to update the CSS value using setState, the items don’t re-render and I get an error saying "discs.map is not a function". Am I using the set state hook correctly? Should i be using the setState hook for a task like this i.e animating position of items?

// Main Component

function App() {
   const [discs, setDiscs] = useState([
      { id: 1, top: 100 },
      { id: 2, top: 200 },
      { id: 3, top: 300 },
      { id: 4, top: 400 },
      { id: 5, top: 500 },
      { id: 6, top: 600 },
      { id: 7, top: 700 },
      { id: 8, top: 800 },
      { id: 9, top: 900 },
      { id: 10, top: 1000 },
      { id: 11, top: 1100 },
      { id: 12, top: 1300 }
   ])

function enlargeDisc(e, num) {
      let t = e.target
      if (t.classList.contains('active')) {
         t.classList.remove('active')
         adjustDiscPos(num, true)
      } else {
         t.classList.add('active')
         adjustDiscPos(num, false)
      }
   }

   function adjustDiscPos(n, backToOriginal) {
      console.log(discs)
      discs.forEach((disc) => {
         if (disc.id < n) {
            setDiscs(prevState =>  backToOriginal ? prevState + 300 : prevState - 300)
         }
         if (disc.id > n) {
            setDiscs(prevState =>  backToOriginal ? prevState - 300 : prevState + 300)
         }
      })
   }

  return (
    <div className="App">
      <div className="container">
         <div className="wrapper" style={{bottom: scroll}}>
            {discs.map((item) => (
               <div className ='disc' key={item.id} data-index={item.id} style={{top: item.top + 'px'}} onClick={(e)=> enlargeDisc(e, item.id)} ></div>
            ))}
        </div>
      </div>
    </div>
  );
}

export default App;

CSS

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

.disc {
   position: absolute;
   transform:
      translate(-50%, -50%) rotateX(90deg) scale(1);
   width: 10em;
   height: 10em;
   transform-style: preserve-3d;
   cursor: pointer;
   background-image:
   radial-gradient(rgba(0, 0, 0, 0), rgb(22, 22, 22) 95%), 
   url('./img/cd3.png');
   background-size: 100% 100%;
   transition: all 0.5s ease-in-out; 
}

.disc.active {
   transform:
   translate(-50%, -50%) rotateX(0deg) scale(1.5);
}

>Solution :

I am assuming here that it is the value of top you wish to manipulate. I am also assuming that you wish to leave the disc with id equal to n as it is. Correct me if I’m wrong.

What you need to do is to create a temporary array and add the new values to that array. Then, when that is done, you call setDiscs with the temporary array as an argument.

let tmp_discs = [];

discs.forEach((disc) => {
  if (disc.id < n) {
    tmp_discs[disc.id] = backToOriginal ? disc.top + 300 : disc.top - 300;
  } else if (disc.id > n) {
    tmp_discs[disc.id] = backToOriginal ? disc.top - 300 : disc.top + 300;
  } else {
    tmp_discs[disc.id] = disc.top;
  }
})

setDiscs(tmp_discs);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading