Как мне упорядочить события в useEffect в React

#javascript #reactjs

#javascript #reactjs

Вопрос:

В главном файле приложения (App.js ) У меня есть этот код, <button> здесь можно отключить компонент «Выпадающий список»

 return (
    <div>
      <button
        onClick={() => {
          console.log("App button"); // First
          setShowDropDown(!showDropDown);
        }}
      >
        Toggle Dropdown
      </button>
      {showDropDown ? (
        <Dropdown
          selected={selected}
          onSelectedChange={setSelected}
          options={options}
        />
      ) : null}
    </div>
  );
 

В выпадающем файле компонента (Dropdown.js ) Это событие onBodyClick делает выпадающее меню неактивным при нажатии на любое место, кроме самого выпадающего меню.
Цель здесь — отменить событие с помощью функции очистки useEffect при нажатии на кнопку. Проблема в том, что когда я нажимаю кнопку, порядок того, что произошло, примерно такой :

  • Сначала: onClick событие кнопки и «размонтирование».
  • Второе: onBodyClick событие.
  • Наконец: очистка. Этот порядок создает проблему, когда я нажимаю на кнопку, потому что событие происходит после размонтирования. Как я могу это решить? ошибка: не удается прочитать свойство ‘contains’ из null
   useEffect(() => {
    const onBodyClick = (event) => {
      console.log("event");   // Second
      if (ref.current.contains(event.target)) {
        return;
      }
      setOpen(false);
    };
    document.body.addEventListener("click", onBodyClick);
    return () => {
      console.log("cleanup");  // Finally
      document.body.removeEventListener("click", onBodyClick);
    };
  }, []);
 

Комментарии:

1. Не удается прочитать свойство ‘contains’ из null

Ответ №1:

Похоже, вам просто нужно сначала проверить, существует ли ссылка:

 const onBodyClick = (event) => {
  if (!ref.current) {
    // Component is unmounting
    // below line could be used or commented out; since the component is unmounting,
    // the state should not make a difference
    // setOpen(false);
    return
  }
  if (ref.current.contains(event.target)) {
    // Component is not unmounting, and click was inside ref
    return;
  }
  // Component is not unmounting, and click was outside ref
  setOpen(false);
};
 

Ответ №2:

У меня такая же проблема, и это работает для меня

 
if(this.wrapperRef amp;amp; !this.wrapperRef.contains(event.target) {
 this.setState({visibility: false});
}

 

Я проверяю, существует ли wrapperRef, и я проверяю, содержит ли оболочка элемент Html

Я знаю, что вы используете перехватчики реакции, но идея та же.