Реагировать на хуки против eventListener

Итак ... Я пробовал useEffect, но обнаружил странное поведение. У меня состояние в тупой составляющей. Я вызываю useEffect и добавляю в него новый eventListener. Этот прослушиватель событий должен изменить состояние при заданном условии. Проблема в том, что состояние никогда не меняется ... Идеи?

const componentToRender=()=>{
    const [renderStatus, changeRenderStatus]=useState(false);
    const [transitionStatus, changeTransitionStatus]=useState(false);
    if(!renderStatus){
        useEffect(()=>{
            window.addEventListener("transitionend",(event)=>{
                if(event.propertyName==="width"){
                    changeTransitionStatus(transitionStatus?false:true);
                }
            })
        })
        changeRenderStatus(true)
    }
    return (transitionStatus)?<div> First case </div>:<div> Second case</div>
}

есть еще одна функция с некоторыми манипуляциями с DOM onMouseOver.

Эта функция должна изменить состояние прослушивателя событий, но это не так.


person Marco Sciortino    schedule 08.02.2019    source источник
comment
пожалуйста, опубликуйте свой соответствующий код   -  person Shubham Khatri    schedule 09.02.2019


Ответы (1)


  1. вы не можете использовать хуки внутри оператора if, см. правила-хуки
  2. вы должны вернуть функцию очистки из ваших useEffect хуков, чтобы удалить прослушиватель событий и избежать утечек памяти
  3. вы, вероятно, хотите, чтобы эффект запускался только один раз, поэтому укажите пустой массив в качестве второго аргумента для useEffect (я не думаю, что вам нужен renderStatus)
  4. внутри useEffect при вызове установщика состояния предпочитайте функциональную форму, чтобы у вас всегда было свежее значение состояния.

пример

const componentToRender = () => {
  //const [renderStatus, changeRenderStatus] = useState(false);
  const [transitionStatus, changeTransitionStatus] = useState(false);

  // No condition
  useEffect(() => {
    const handler = (event) => {
      if (event.propertyName === "width") {
        //passe a function to state setter to get fresh state value
        changeTransitionStatus(transitionStatus => transitionStatus ? false : true);
      }
    };

    window.addEventListener("transitionend", handler);

    // clean up
    return () => window.removeEventListener("transitionend", handler);
  }, []); // empty array => run only once

  return (transitionStatus) ? <div> First case </div> : <div> Second case</div>
}
person Mohamed Ramrami    schedule 09.02.2019