javascript 下拉列表未出现在React表单中

j91ykkif  于 11个月前  发布在  Java
关注(0)|答案(1)|浏览(117)

我已经在react中创建了一个JavaScript组件,但是当我点击按钮时,列表不会出现。我已经尝试过gpt的,但是没有帮助。下面是三个使用代码的jsx文件。
DropdownList.jsx

import PropTypes from "prop-types";

function DropdownList({ listLength, handleOptionSelect, dropdownliname }) {
    const listItems = Array.from({ length: listLength }, (_, index) => (
        <li key={index}>
            <a
                className="block w-full whitespace-nowrap bg-transparent px-4 py-2 text-sm font-normal text-neutral-700 hover:bg-neutral-100 active:text-neutral-800 active:no-underline disabled:pointer-events-none disabled:bg-transparent disabled:text-neutral-400 dark:text-neutral-200 dark:hover:bg-neutral-600"
                href="#"
                data-te-dropdown-item-ref
                onClick={() => handleOptionSelect(index)}
            >
                {dropdownliname(index + 1)}
            </a>
        </li>
    ));

    return (
        <ul
            className="absolute z-[1000] float-left m-0 hidden min-w-max list-none overflow-hidden rounded-lg border-none bg-white bg-clip-padding text-left text-base shadow-lg dark:bg-neutral-700 [&[data-te-dropdown-show]]:block"
            aria-labelledby="dropdownMenuButton1"
            data-te-dropdown-menu-ref
        >
            {listItems}
        </ul>
    );
}

DropdownList.propTypes = {
    listLength: PropTypes.number.isRequired,
    handleOptionSelect: PropTypes.func.isRequired,
    dropdownliname: PropTypes.func.isRequired,
};

export default DropdownList;

字符串
DropdownButton.jsx

import { useEffect, useState } from "react";
import { Dropdown, Ripple, initTE } from "tw-elements";
import PropTypes from "prop-types";
import DropdownList from "./DropdownList";

initTE({ Dropdown, Ripple });

function DropdownButton(props) {
    const [selectedOption, setSelectedOption] = useState(null);
    const [dropdownListLength, setDropdownListLength] = useState(null);

    useEffect(() => {
        setDropdownListLength(parseInt(props.dropdownlistLength, 10));
    }, [props.dropdownlistLength]); // Update dropdownListLength on prop change

    const handleOptionSelect = (optionId) => {
        setSelectedOption(optionId);
    };

    const dropdownliname = (index) => props[`dropdownliname${index}`];

    const buttonColorClass =
        selectedOption !== null ? "text-black" : "text-gray-400";

    return (
        <div className="relative" data-te-dropdown-ref>
            <label
                htmlFor={props.dropdownlabelhtmlfor}
                className="mb-4 px-1 text-sm text-start font-medium text-grey-900"
            >
                {props.dropdownlabelname}
            </label>
            <button
                className={`flex items-center justify-between text-end w-full px-3 py-2 mt-2 mb-4 text-sm border-2 border-black rounded-lg focus:border-indigo-500 focus:outline-none ${buttonColorClass}`}
                type="button"
                id="dropdownMenuButton1"
                data-te-dropdown-toggle-ref
                aria-expanded="false"
                data-te-ripple-init
                data-te-ripple-color="light"
            >
                {selectedOption !== null
                    ? dropdownliname(selectedOption + 1)
                    : props.dropdownbuttonname}
                <span className="mr-2 w-2">
                    <svg
                        xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 20 20"
                        fill="currentColor"
                        className="h-5 w-5"
                    >
                        <path
                            fillRule="evenodd"
                            d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
                            clipRule="evenodd"
                        />
                    </svg>
                </span>
            </button>
            {dropdownListLength && (
                <DropdownList
                    listLength={dropdownListLength}
                    handleOptionSelect={handleOptionSelect}
                    dropdownliname={dropdownliname}
                />
            )}
        </div>
    );
}

DropdownButton.propTypes = {
    dropdownbuttonname: PropTypes.string.isRequired,
    dropdownlabelname: PropTypes.string.isRequired,
    dropdownlabelhtmlfor: PropTypes.string.isRequired,
    dropdownlistLength: PropTypes.number.isRequired,
};

Array.from(
    { length: DropdownButton.propTypes.dropdownlistLength },
    (_, index) => {
        DropdownButton.propTypes[`dropdownliname${index + 1}`] =
            PropTypes.string.isRequired;
    }
);

export default DropdownButton;


BusinessRegistrationForm.jsx

import Button from "./Button";
import DropdownButton from "./DropdownButton";
import InputField from "./InputField";
import Navbar from "./Navbar";

function BusinessRegistrationForm() {
    return (
        <div>
            <Navbar />
            <div className="flex justify-center items-center py-36">
                <div className="flex justify-center py-12">
                    <div className="w-[590px]">
                        <h3 className="pb-6 text-center text-4xl font-extrabold text-dark-grey-900">
                            Let us know more <br />
                            about your business.
                        </h3>
                        {/* <div className="mt-6">
                            <h1 className="text-black">Select type of account</h1>

                            <div className="mt-3 md:flex md:items-center md:-mx-2">
                                <button className="flex justify-center w-full px-6 py-3 text-black rounded-md md:w-auto md:mx-2 focus:outline-none">
                                    <svg
                                        xmlns="http://www.w3.org/2000/svg"
                                        className="w-6 h-6"
                                        fill="none"
                                        viewBox="0 0 24 24"
                                        stroke="currentColor"
                                        strokeWidth="2"
                                    >
                                        <path
                                            strokeLinecap="round"
                                            strokeLinejoin="round"
                                            d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
                                        />
                                    </svg>

                                    <span className="mx-2">client</span>
                                </button>

                                <button className="flex justify-center w-full px-6 py-3 mt-4 text-black border border-blue-500 rounded-md md:mt-0 md:w-auto md:mx-2 focus:outline-none">
                                    <svg
                                        xmlns="http://www.w3.org/2000/svg"
                                        className="w-6 h-6"
                                        fill="none"
                                        viewBox="0 0 24 24"
                                        stroke="currentColor"
                                        strokeWidth="2"
                                    >
                                        <path
                                            strokeLinecap="round"
                                            strokeLinejoin="round"
                                            d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
                                        />
                                    </svg>

                                    <span className="mx-2">worker</span>
                                </button>
                            </div>
                        </div> */}
                        <form>
                            <div className="grid grid-cols-1 gap-x-8 gap-y-4 mt-8 md:grid-cols-2">
                                <div>
                                    <InputField
                                        inputfieldid="businessname"
                                        inputfieldtype="text"
                                        inputfieldplaceholder="John & Sons"
                                        inputfieldhtmlfor="businessname"
                                        inputfieldlabelname="Registered Name"
                                    />
                                </div>

                                <div>
                                    <InputField
                                        inputfieldid="businesscity"
                                        inputfieldtype="text"
                                        inputfieldplaceholder="Islamabad"
                                        inputfieldhtmlfor="businesscity"
                                        inputfieldlabelname="City"
                                    />
                                </div>

                                <div>
                                    <InputField
                                        inputfieldid="businesscontactnumber"
                                        inputfieldtype="text"
                                        inputfieldplaceholder="XXXX-XXXXXXX"
                                        inputfieldhtmlfor="businesscontactnumber"
                                        inputfieldlabelname="Contact Number"
                                    />
                                </div>

                                <div>
                                    <InputField
                                        inputfieldid="businessemail"
                                        inputfieldtype="email"
                                        inputfieldplaceholder="[email protected]"
                                        inputfieldhtmlfor="businessemail"
                                        inputfieldlabelname="Work Email"
                                    />
                                </div>

                                <div>
                                    <DropdownButton
                                        dropdownbuttonname="select range"
                                        dropdownlabelname="No. of Employees"
                                        dropdownlistLength={3}
                                        dropdownlabelhtmlfor="employeesno"
                                        dropdownliname0="1 - 5"
                                        dropdownliname1="5 - 10"
                                        dropdownliname2="10 - 15"
                                        dropdownliname3="15 - 20"
                                    />
                                </div>

                                <div>
                                    <InputField
                                        inputfieldid="businesscategory"
                                        inputfieldtype="text"
                                        inputfieldplaceholder="e.g. IT, Marketing, etc."
                                        inputfieldhtmlfor="businesscategory"
                                        inputfieldlabelname="Field of Work"
                                    />
                                </div>

                                <div>
                                    <DropdownButton
                                        dropdownbuttonname="public, private"
                                        dropdownlabelname="Business Type"
                                        dropdownlistLength={5}
                                        dropdownlabelhtmlfor="businesstype"
                                        dropdownliname1="Public Business"
                                        dropdownliname0="Public Business 0"
                                        dropdownliname2="Private Business"
                                        dropdownliname3="Private Business 3"
                                        dropdownliname4="Public Business 4"
                                        dropdownliname5="Private Business 5"
                                    />
                                </div>
                            </div>
                            <div className="pb-2 px-24">
                                <Button buttonname="add business" />
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    );
}

export default BusinessRegistrationForm;


上面提供的代码是所有与按钮组件链接的代码。当我更改某些代码时,它可以工作,但当页面刷新或再次访问页面时,它停止工作。
下面是提供的代码的codesandbox的链接:https://codesandbox.io/s/dropdown-list-error-vcjqsn?file=/src/index.js

yyhrrdl8

yyhrrdl81#

好吧,所以只有一对夫妇的问题,造成的行为.
其中主要有:

  • hidden被添加到ul元素,这意味着它总是隐藏的
  • 为了解决这个问题,我在DropdownButton组件中添加了一些状态,以控制单击按钮时的打开/关闭状态
  • 您可能希望将其扩展为包括监听用户在服务器外部的单击(例如useOnClickOutside钩子
  • z索引不起作用(至少在沙盒中不起作用),所以列表有时会显示在其他列表后面(更宽的屏幕),所以我将其设置为z-10而不是z-[1000],因为这在docs中是一个低值,而且我个人不喜欢在阅读this articlez-index的大值

Here's the working sandbox
下面您可以看到DropdownButton中添加的状态,以确定列表是否打开:

// DropdownButton.jsx
// 

function DropdownButton(props) {
  const [selectedOption, setSelectedOption] = useState(null);
  const [dropdowListOpen, setDropdowListOpen] = useState(false);
  const [dropdownListLength, setDropdownListLength] = useState(null);

  useEffect(() => {
    setDropdownListLength(parseInt(props.dropdownlistLength, 10));
  }, [props.dropdownlistLength]); // Update dropdownListLength on prop change

  const handleOptionSelect = (optionId) => {
    setSelectedOption(optionId);
    setDropdowListOpen(false);
  };

  const dropdownliname = (index) => props[`dropdownliname${index}`];

  const buttonColorClass =
    selectedOption !== null ? "text-black" : "text-gray-400";

  return (
    <div className="relative" data-te-dropdown-ref>
      <label
        htmlFor={props.dropdownlabelhtmlfor}
        className="mb-4 px-1 text-sm text-start font-medium text-grey-900"
      >
        {props.dropdownlabelname}
      </label>
      <button
        className={`flex items-center justify-between text-end w-full px-3 py-2 mt-2 mb-4 text-sm border-2 border-black rounded-lg focus:border-indigo-500 focus:outline-none ${buttonColorClass}`}
        type="button"
        id="dropdownMenuButton1"
        data-te-dropdown-toggle-ref
        aria-expanded="false"
        data-te-ripple-init
        data-te-ripple-color="light"
        onClick={() => setDropdowListOpen(true)}
      >
        {selectedOption !== null
          ? dropdownliname(selectedOption + 1)
          : props.dropdownbuttonname}
        <span className="mr-2 w-2">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 20 20"
            fill="currentColor"
            className="h-5 w-5"
          >
            <path
              fillRule="evenodd"
              d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
              clipRule="evenodd"
            />
          </svg>
        </span>
      </button>
      {dropdownListLength && (
        <DropdownList
          dropdowListOpen={dropdowListOpen}
          listLength={dropdownListLength}
          handleOptionSelect={handleOptionSelect}
          dropdownliname={dropdownliname}
        />
      )}
    </div>
  );
}

字符串
然后由DropdownList组件使用

// DropdownList.jsx
// 

function DropdownList({
  dropdowListOpen,
  listLength,
  handleOptionSelect,
  dropdownliname
}) {
  const listItems = Array.from({ length: listLength }, (_, index) => (
    <li key={index}>
      <a
        className="block w-full whitespace-nowrap bg-transparent px-4 py-2 text-sm font-normal text-neutral-700 hover:bg-neutral-100 active:text-neutral-800 active:no-underline disabled:pointer-events-none disabled:bg-transparent disabled:text-neutral-400 dark:text-neutral-200 dark:hover:bg-neutral-600"
        href="#"
        data-te-dropdown-item-ref
        onClick={() => handleOptionSelect(index)}
      >
        {dropdownliname(index + 1)}
      </a>
    </li>
  ));

  const listClassNames = `absolute z-10 float-left m-0 ${
    dropdowListOpen ? "" : "hidden"
  } min-w-max list-none overflow-hidden rounded-lg border-none bg-white bg-clip-padding text-left text-base shadow-lg dark:bg-neutral-700 [&[data-te-dropdown-show]]:block`;

  return (
    <ul
      className={listClassNames}
      aria-labelledby="dropdownMenuButton1"
      data-te-dropdown-menu-ref
    >
      {listItems}
    </ul>
  );
}


我还要指出,使用aul作为下拉列表在语义上可能不太明智,使用select作为下拉列表当然更合适,但是样式化它们可能有点困难。说到这里,我推荐React Dropdown库,因为它为你处理了很多样式化(即使它有一些膨胀)。
但是不要让这一点阻止你,表单本身看起来很棒,其余的代码也写得很好!

相关问题