簡體   English   中英

在選擇項目或單擊項目外部時關閉列表項目下拉列表

[英]Closing a list item dropdown on selecting an item or clicking outside it

我在我的 react js 項目中創建了一個下拉列表,其中包含列表項(下拉項在此處由 ul 和 li 標簽顯示)。

我面臨的問題是,在選擇任何項目時,狀態值會發生變化,但下拉列表不會關閉,當我單擊它之外的任何地方時,它不會關閉。 請幫幫我,這是同一個 repo 的有效代碼和框 url

在這里查看

我也在下面分享代碼。

應用程序.js

import React, { Component, useState } from "react";
import Dropdown from "./dropdown";
import "./dropdown.css";

const App = () => {
  const [value, setValue] = useState("");
  const [showDropdown, setShowDropdown] = useState(false);

  const selectedValue = (value) => {
    console.log(value);
    setValue(value);
  };
  const onSelectItem = () => {
    console.log("12");
    setShowDropdown(false);
  };

  return (
    <section className="shadow-border" id="FlightsForm">
      <div className="top-sec d-flex">
        <div className="left-side">
          <span
            className="custm-dropdown"
            onClick={() => setShowDropdown(true)}
          >
            <span style={{ backgroundColor: "grey", color: "white" }}>
              {value.tripType}
            </span>
            <span className="dropdown-icon"> </span>
            <Dropdown
              selectedValue={selectedValue}
              onSelectItem={onSelectItem}
              showDropdown={showDropdown}
            />
          </span>
        </div>
      </div>
    </section>
  );
};

export default App;

下拉菜單

import React from "react";
import { useState, useEffect } from "react";

const TripTypeDropdown = (props) => {
  const [values, setValues] = useState([
    { tripType: "One Way", value: 1 },
    { tripType: "Return", value: 2 },
    { tripType: "Multi- City", value: 3 },
  ]);
  const [selectedItem, setSelectedItem] = useState({
    tripType: "One Way",
    value: 1,
  });
  useEffect(() => {
    props.selectedValue(selectedItem);
    console.log(selectedItem);
  }, [selectedItem]);

  const selectItemFromList = (index) => {
    const itemSelected = values[index];
    setSelectedItem(itemSelected);
    props.onSelectItem();
  };
  const getActiveClassName = (item) => {
    if (selectedItem) {
      if (item.tripType == selectedItem.tripType) return "active";
      else return "";
    }
  } ;
  return (
    <React.Fragment>
      <div
        className={`dropdown-modal sm-modal ripple trip-type-dropdown`}
        style={{ display: `${props.showDropdown ? "block" : "none"}` }}
      >
        <ul>
          {console.log(values)}
          {values.map((item, index) => (
            <li
              className={getActiveClassName(item)}
              onClick={() => selectItemFromList(index)}
              key={index}
               style={{backgroundColor:'yellow',border:"1px solid black",listStyle:"none"}}
            >
              {item.tripType}
            </li>
          ))}
        </ul>
      </div>
    </React.Fragment>
  );
};

export default TripTypeDropdown;

您需要停止從下拉組件到其父 span 元素的 click 事件冒泡。 單擊時,您需要傳遞事件參數並調用事件對象的stopPropagation函數

這是condesandbox

下拉菜單

const selectItemFromList = (e,index) => {
    e.stopPropagation();

...

<li
     className={getActiveClassName(item)}
     onClick={(e) => selectItemFromList(e,index)}
     key={index}

還添加了外部點擊的代碼。

const ref = useRef();

...

useEffect(() => {
    document.addEventListener("click", handleDropdownClick);
  }, [ref]);

const handleDropdownClick = (e) => {
    e.stopPropagation();
    if (ref.current && ref.current.contains(e.target)) {
      setShowDropdown(true);
    } else {
      setShowDropdown(false);
    }
  };

...

<span
     ref={ref}
     className="custm-dropdown"
     onClick={handleDropdownClick}
 >

您應該停止將單擊事件從列表項傳播到外部跨度,這會阻止從父項再次關閉下拉列表的任何嘗試。

const selectItemFromList = (index) => (e) => {
  e.stopPropagation();
  const itemSelected = values[index];
  setSelectedItem(itemSelected);
  props.onSelectItem();
};

...

<li
  key={index}
  ...
  onClick={selectItemFromList(index)}
  ...
>
  {item.tripType}
</li>

要處理外部點擊,您將 React ref 附加到下拉 div 並使用useEffect鈎子將onClick事件偵聽器添加到 widow 對象,並檢查onClick的事件目標是否不包含在下拉 div 中。

useEffect(() => {
  const outsideClickHandler = (e) => {
    if (props.showDropdown && !outsideRef.current?.contains(e.target)) {
      props.onSelectItem(false);
    }
  };

  window.addEventListener("click", outsideClickHandler);

  return () => window.removeEventListener("click", outsideClickHandler);
}, [props]);

...

<div
  ref={outsideRef}
  ...
>
  ...
</div>

演示

編輯關閉列表項下拉選擇項或單擊外部項

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM