Click 事件未在移动视图中的 React Select 中捕获

问题描述 投票:0回答:0
import DatePicker from "@/src/Components/Common/DatePicker"
import { SEARCH_PAGE } from "@/src/Constants/AppPaths"
import { DATE_FORMATS } from "@/src/Constants/GenericConstants"
import { strings } from "@/src/Constants/Strings"
import { useDetectOutsideClick } from "@/src/Hooks/useDetectOutsideClick"
import useOptions from "@/src/Hooks/useOptions"
import React, { useRef, useState, useEffect, Fragment } from "react"
import { getCategories, getCities, getCountries } from "@/src/Network/RequestBuilder"
import {
  capitalize,
  getDateString,
  splitAndMergeStringByHyphen,
  stringToDate,
  useIfMobile,
} from "@/src/Utils/GenericUtils"
import Heading from "@/src/Components/Common/Heading"

import cx from "clsx"
import { ChevronRight } from "react-feather"
import { BiCalendar, BiCategory, BiListUl, BiSearch, BiUser } from "react-icons/bi"
import { HiOutlineChevronDown, HiOutlineSearch, HiSearch } from "react-icons/hi"
import { IoLocationOutline } from "react-icons/io5"
import Select, { components } from "react-select"
import { CancelIcon, IconFilter } from "../../icons/svg-icons"
import SearchChips from "../../SearchPage/SearchChips"
import { BottomSheet } from "../BottomSheet"
import Button from "../Button"
import InputMobile from "../FormInputMobile"
import styles from "./index.module.scss"
import MobileOptions from "./MobileOptions"

const RenderComponent = ({ children, ...props }) => {
  const { isMobile, setOpen, router } = props.selectProps
  return (
    <>
      {isMobile && <span className={styles.selectIcon}>{<HiSearch />}</span>}
      <div className={cx(styles.selectContent, "flexGrow")}>{children}</div>
      {isMobile && (
        <span
            // This method does not execute upon Click
          onClick={() => {
            console.log("BRU")
            router.push("#filters", null, {
              shallow: true,
            })
            setOpen(true)
          }}
          className={styles.selectIcon}
        >
          <IconFilter />
        </span>
      )}
    </>
  )
}

const Control = ({ children, ...props }) => (
  <Fragment>
    <components.Control {...props}>
      <RenderComponent {...props}>{children}</RenderComponent>
    </components.Control>
  </Fragment>
)

const SearchBar = (props) => {
  const isMobile = useIfMobile()
  const screenOptionsRef = useRef()
  const {
    router,
    searchChips: ChipsComponent,
    //  setTypedValue
  } = props

  const [showOptionsScreen, setShowOptionsScreen] = useDetectOutsideClick(screenOptionsRef, false)
  const { addToRecentSearches, recentSearches, formatOptions, options, RecentSearchComponent, AllCategoriesBtn } =
    useOptions(getCategories)

  let prefillValue = ""

  // prefilling keyword search
  if (router?.query?.keyword) {
    let target = router?.query?.keyword
    options?.forEach((optionLabel) => {
      optionLabel?.options?.forEach((option) => {
        if (option?.slug === target || option?.value === target) {
          prefillValue = option
        }
      })
    })
  }

  const [value, setValue] = useState("")
  const [inputValue, setInputValue] = useState("")
  const [isMenuOpen, setIsMenuOpen] = useState(false)
  const [noOptions, setNoOptions] = useState(false)
  const [open, setOpen] = useState(false)

  useEffect(() => {
    !isMobile && setOpen(false)
  }, [isMobile])

  const typeQuery = () => {
    return router.query?.browse_by ?? "search"
  }

  useEffect(() => {
    props.setShowContent(!showOptionsScreen)
  }, [showOptionsScreen])

  const handleInputSearch = () => {
    const { browse_by } = router.query

    if (inputValue) {
      setIsMenuOpen(false)
      addToRecentSearches(inputValue, browse_by)
      const queryObj = { ...router.query }
      delete queryObj["browse_by"]
      router.push({ pathname: `/${typeQuery()}`, query: { ...queryObj, keyword: inputValue } }, null, {
        shallow: true,
      })
    } else {
      const routerObj = { ...router.query }
      delete routerObj.keyword
      router.push({ pathname: `/${typeQuery()}`, query: {} }, null, { shallow: true })
    }
  }

  const handleSearchClick = (item, e) => {
    setIsMenuOpen(false)
    if (!item) {
      if (router.pathname === "/") return
      if (inputValue) {
        setInputValue("")
        // setTypedValue("")
      }
      setValue("")
      const queryObj = { ...router.query }
      const isKeyword = e?.removedValues[0]?.id ? false : true
      isKeyword ? delete queryObj.keyword : delete queryObj.category
      router.push({ pathname: SEARCH_PAGE, query: { ...queryObj } }, null, { shallow: true })
    } else {
      if (item.isCached) {
        setValue(item)
        const routerQuery = { ...router.query }
        // use the type associated with the recent search rather using what's in the URL query
        delete routerQuery["browse_by"]
        if (item?.label) {
          routerQuery["keyword"] = item.label
        }

        router.push({ pathname: item?.type ? `/${item.type}` : `/${typeQuery()}`, query: { ...routerQuery } }, null, {
          shallow: true,
        })
      } else {
        const routerQuery = { ...router.query }
        delete routerQuery["browse_by"]

        if (item?.slug) {
          routerQuery["category"] = item.slug
        }

        router.push({ pathname: `/${typeQuery()}`, query: { ...routerQuery } }, null, {
          shallow: true,
        })
      }
    }
  }

  const customStyles = {
    indicatorSeparator: (provided) => ({
      ...provided,
      display: "none",
    }),

    placeholder: (provided) => ({
      ...provided,
      color: "#a3a3a3",
    }),

    control: (provided, { isFocused, isMenuOpen }) => ({
      ...provided,
      boxShadow: "none",
      minHeight: isMobile ? "48px" : "56px",
      backgroundColor: props.compactView ? "#fff" : "rgba(227, 227, 227, 0.2)",
      borderColor: isFocused ? "#dbdee1" : props.compactView ? "#e3e3e3" : "#e3e3e3",
      "&:hover": {
        borderColor: isMenuOpen ? "#436347" : "",
        cursor: "text",
      },
    }),

    indicatorsContainer: (provided) => ({
      ...provided,
      width: "2.125rem",
      justifyContent: "center",
      fontSize: "1.3rem",
      color: "#00a651",
      cursor: "pointer",
    }),

    dropdownIndicator: (provided) => ({
      ...provided,
      display: "none",
    }),

    valueContainer: (provided) => ({
      ...provided,
      padding: "2px 1rem",
    }),

    menu: (provided) => ({
      ...provided,
      width: "100%",
      zIndex: 2,
    }),

    option: (provided, state) => ({
      ...provided,
      display: "flex",
      alignItems: "center",
      gap: "1rem",
      cursor: "pointer",
      backgroundColor: "#fff",
      color: "#1e1e1e",
      "&:hover": {
        backgroundColor: "#f9f9f9",
      },
    }),
  }

  // if there are no options that matches your input string, execute a new keyword search on Enter
  const handleKeyPressDown = (e) => {
    if (isMobile && e.code === "Enter") {
      handleInputSearch()
      setShowOptionsScreen(false)
      return
    }
    if (noOptions && inputValue) {
      if (e.code === "Enter") {
        handleInputSearch()
      }
    }
  }

  return (
    <>
      <div
        className={cx(
          styles.searchBarOuter,
          props.className && props.className,
          props.compactView && styles.compactView
        )}
      >
        <div className={isMobile ? cx(styles.searchMobile, "flex") : "flexGrow"}>
          <Select
            router={router}
            setOpen={setOpen}
            isMobile={isMobile}
            key={JSON.stringify(recentSearches.length)}
            value={prefillValue || value}
            inputValue={inputValue}
            options={options}
            placeholder="Search the website"
            formatOptionLabel={formatOptions}
            onChange={handleSearchClick}
            menuIsOpen={isMenuOpen}
            // menuIsOpen={true}
            closeMenuOnSelect={false}
            indicatorsContainer={false}
            onKeyDown={handleKeyPressDown}
            onMenuOpen={() => {
              if (props.showSingleScreen) {
                setShowOptionsScreen(true)
              } else {
                setIsMenuOpen(true)
              }
            }}
            onInputChange={(value, action) => {
              if (action.action === "input-change") {
                // setTypedValue(value)
                setInputValue(value)
              }
            }}
            onMenuClose={() => setIsMenuOpen(false)}
            noOptionsMessage={() => {
              setNoOptions(true)
              return null
            }}
            isClearable={true}
            debounceTimeout={200}
            classNamePrefix="select"
            className={cx(styles.selectOuter, "flexGrow")}
            styles={customStyles}
            components={{ Control, DropdownIndicator: () => null }}
          />
        </div>

        {isMobile ? (
          <></>
        ) : (
          <Button
            onClick={handleInputSearch}
            icon={<HiOutlineSearch />}
            size="lg"
            style={{ "--btn-min-width": props.compactView ? "62px" : "130px" }}
          >
            {!props.compactView && strings.search}
          </Button>
        )}
      </div>
      {/* {showOptionsScreen && (
        <MobileOptions
          RecentSearchComponent={RecentSearchComponent}
          screenOptionsRef={screenOptionsRef}
          handleSearchClick={handleSearchClick}
          setShowFooter={props.setShowFooter}
          options={options}
          setShowOptionsScreen={setShowOptionsScreen}
        />
      )} */}
    </>
  )
}
export default SearchBar

SearchBar.defaultProps = {
  setTypedValue: () => {},
}

Mobile View
中,在我的
RenderComponent
中,单击包含
IconFilter
的span 标签时,没有任何反应。点击事件不会被捕获,相应的
onClick
方法也不会被执行。但是,如果我要省略
isMobile
检查,则 Click 事件会被捕获。相同的代码适用于桌面视图,但对于
mobile view
,不会捕获点击方法。我正在使用
React Select
。如何在移动视图中单击 span 标签?

javascript reactjs next.js onclick react-select
© www.soinside.com 2019 - 2024. All rights reserved.