Реактивные хуки против eventListener - PullRequest
0 голосов
/ 09 февраля 2019

Итак ... Я пытался использовать эффект, но обнаружил странное поведение.У меня есть состояние в немом компоненте.Я вызываю 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.

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

1 Ответ

0 голосов
/ 09 февраля 2019
  1. вы не можете использовать хуки внутри оператора if, см. правила хуков
  2. вы должны вернуть функцию очистки из ваших useEffect хуков, чтобы удалить событиеслушатель и избегайте утечек памяти
  3. вы, вероятно, хотите, чтобы эффект запускался только один раз, поэтому предоставьте пустой массив в качестве второго аргумента для использованияEffect (я не думаю, что вам нужно 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>
}
...