REACT:使用 setState 钩子重新渲染组件时出错

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

我正在尝试更改几个项目的内联样式 属性,这些项目的位置信息存储在 useState 挂钩中,以及每个呈现的项目的样式 属性。我想更改所有项目的 CSS 值,但我单击的项目除外。我设计了一个函数来执行此操作,但是当我尝试使用 setState 更新 CSS 值时,项目不会重新呈现并且我收到一条错误消息“discs.map 不是函数”。我是否正确使用了设置状态挂钩?我应该使用 setState 挂钩来完成这样的任务,即设置项目的动画位置吗?

// 主要成分

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);
}

adjustDiscPos 中,您正在调用 setDiscs300 prevState - 300.

的减法值

这会将 NaN 推送到 discs,从而导致您的错误。

您应该在 forEach 中计算一个新数组,然后只调用 setDiscs 一次。

以 Radu Dita 所说的为基础

In adjustDiscPos you are calling setDiscs with the value of a subtraction of an array and 300 prevState - 300. This will push NaN to discs and hence your error. You should compute a new array in your forEach and then call setDiscs only once.

这意味着您应该使用 setDiscs 一次(prevState 是对当前 discs 值的引用),并通过 map 或其他方式对其进行 arrayu 操作。

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 };
      })

请务必记住不要直接改变 prevState,因为它是对当前状态变量的引用,而是使用一些数组函数 returns 一个新值。

我在这里假设它是您想要操纵的 top 的值。我还假设您希望 id 等于 n 的光盘保持原样。如果我错了,请纠正我。

您需要做的是创建一个临时数组并将新值添加到该数组。然后,完成后,您可以使用临时数组作为参数调用 setDiscs

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);