Estoy tratando de cambiar una propiedad de estilo en línea de varios elementos que tienen información de posición almacenada en un enlace useState y también en la propiedad de estilo de cada elemento representado. Quería cambiar el valor CSS de todos los elementos excepto en el que hice clic. Desarrollé una función para hacerlo, sin embargo, cuando trato de actualizar el valor de CSS usando setState, los elementos no se vuelven a renderizar y aparece un error que dice "discs.map no es una función". ¿Estoy usando correctamente el enlace de estado establecido? ¿Debería usar el gancho setState para una tarea como esta, es decir, animar la posición de los elementos?
// Componente principal
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); }Estoy suponiendo aquí que es el valor de la top que desea manipular. También asumo que desea dejar el disco con una identificación igual a n tal como está. Corrígeme si me equivoco.
Lo que debe hacer es crear una matriz temporal y agregar los nuevos valores a esa matriz. Luego, cuando haya terminado, llame a setDiscs con la matriz temporal como argumento.
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);En adjustDiscPos está llamando a setDiscs con el valor de una resta de una matriz y 300 prevState - 300 .
Esto empujará NaN a los discs y, por lo tanto, su error.
Debe calcular una nueva matriz en su forEach y luego llamar a setDiscs solo una vez.
Construyendo sobre lo que dijo Radu Dita
En adjustDiscPos, está llamando a setDiscs con el valor de una resta de una matriz y 300 prevState - 300. Esto empujará NaN a los discos y, por lo tanto, su error. Debe calcular una nueva matriz en su forEach y luego llamar a setDiscs solo una vez.
Lo que esto significa es que en lugar de usar un forEach y hacer setDiscs para cada elemento en la matriz, se supone que debe usar setDiscs una vez ( prevState es la referencia al valor actual de los discs ) y hacer su operación de matrizu en él a través del map o alguna cosa.
function adjustDiscPos(n, backToOriginal) { console.log(discs) setDiscs(prevState => prevState.map(disc => { const offset = backToOriginal ? 300 : -300; return { id: disc.id, top: disc.id < n ? disc.top + offset : disc.top - offset }; }) Solo asegúrese de recordar no mutar prevState directamente, ya que es una referencia a la variable de estado actual, sino usar alguna función de matriz que devuelva un nuevo valor.