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
.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); }
Advertisement
Answer
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);