8XL
@8XL
Я высокий, но ниже, чем вы подумали.

Drag'n'drop — почему выводится старое состояние в useEffect?

Суть: при событии onMouseDown на див('area') дочернего компонента motion.active : true и далее запускаются слушатели mousemove и mouseup, где mousup обнуляет motion.active : false. Но! После отпускания клавиши мыши и смены её положения, срабатывает (не понимаю каким образом) снова mousedown и задает motion.active : true и запускается все по новой, чего быть не должно.

function App() {
  
  const [motion, setMotion] = React.useState({
    active: false,
    i: null,
    stX: null,
    movX: null,
    movY: null
  })
  
  const handleMouseDown = (e, index) => {
    e.preventDefault()
    const parent = e.target.parentNode.getBoundingClientRect();
    const element = e.target.getBoundingClientRect();

    const x = element.left - parent.left;
    const y = element.top - parent.top;
    setMotion({
      ...motion,
      active: true,
      i: index,
      stX: x
    })
  }

  React.useEffect(()=>{
    window.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('mouseup', handleMouseUp); 
  },[handleMouseDown])


  const handleMouseMove = (e) => {
    if(motion.active) setMotion({
      ...motion,
      movX: e.offsetX,
      movY: e.offsetY
    })
  }

  const handleMouseUp = () => {
    setMotion({
      active: false,
    })
} 

  return (
    <div className="App">
      <Panel  />
      <Search />
      <h3>{`${motion.active}__${motion.movX}++${motion.stX}`}</h3>
      <div 
        className="wrapper"
        >
        {state && state.map((item, index)=>
          <div 
            className="area"
            onMouseDown={(e)=>handleMouseDown(e, index)}>
          <MiniItem
            key={item._id}
            flag={flag}
            resetStateHidden={resetStateHidden}
            setFlag={setFlag}
            item={item}
            index ={index}
            state={state}
            motion={motion}
               
          />
          </div>
          )}
      </div>
    </div>
  );
}


Выручайте, всю голову сломал. Как зафиксировать флаг motion.active до следующего mousedown.

Спасибо.
  • Вопрос задан
  • 94 просмотра
Решения вопроса 1
8XL
@8XL Автор вопроса
Я высокий, но ниже, чем вы подумали.
Практически доведя себя до экзистенциального кризиса так нашел решение. Оставлю на случай, если кто столкнется с потерей состояния из-за слушателя событий внутри хука useEffect.

React.useEffect(()=>{
// добавление слушателя на все окно
    window.addEventListener('mousemove', mouseMove); 
    window.addEventListener('mouseup', mouseUp);
    
      return () => {
// удаление слушателя после обновления эффекта
        window.removeEventListener('mousemove', mouseMove); 
        window.removeEventListener('mouseup', mouseUp);
      }             
    }
  )

// эвент движения
  const mouseMove = (e) => { 
    if(motion.active){
// считаем дельту положения мышки в моменте и первоначального положения
      const delta = e.pageY - motion.stY;

// вот тут и далее ВАЖНО для эффекта(!!!) стэйт функционально задать!
setMotion(motion=>( 
          {
            ...motion,
            y: delta
          }
        )
      )
    }
  }

// эвент отпускания клавиши и конец днд
  const mouseUp = () =>{
    setMotion(motion=>(
      {
        ...motion,
        i: null,
        active: false,
        y: 0,
      })
    )
  }
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы