我正在使用Headlessui Combobox组件,但在与Yup一起使用时遇到了问题.我使用组合框 Select 的值被写入selectedMemory状态变量,没有任何问题,但YUP仍然抛出required错误消息.我肯定漏掉了一点.

表格的类型

// form values for Yup
type RewardCreateFormValues = {
    name: string
    price: number
    quantity: number
    reward: string
}

type Reward = {
    id: string
    name: string
    price: number
    quantity: number
}

const rewards: Reward[] = [
    {
        id: "1",
        name: "Reward 1",
        price: 100,
        quantity: 100
    },
    {
        id: "2",
        name: "Reward 2",
        price: 200,
        quantity: 200
    },
    {
        id: "3",
        name: "Reward 3",
        price: 300,
        quantity: 300
    }
]

为Combobox创建状态和备忘筛选奖励

    const [selectedReward, setSelectedReward] = useState(rewards[0])
    const [query, setQuery] = useState("")

    // it filters the rewards according to the query
    let filteredReward =
        query === ""
            ? rewards
            : rewards.filter(reward => {
                  return reward.name.toLowerCase().includes(query.toLowerCase())
              })

    const rewardOptions = useMemo(() => {
        return filteredReward.map((reward: Reward) => ({
            name: reward.name,
            id: reward.id
        }))
    }, [filteredReward])

使用YUP和FORM初始值进行对象验证

    const validationSchema = Yup.object().shape({
        name: Yup.string().required("Required"),
        price: Yup.number().required("Required"),
        quantity: Yup.number().required("Required"),
        reward: Yup.string().required("Required")
    })

    const initialValues: RewardCreateFormValues = {
        name: "",
        price: 0,
        quantity: 0,
        reward: ""
    }

和组合框;

                           <GridItem colSpan={3}>
                                <FormControl>
                                    <Box>
                                        <FormLabel>Select a Reward</FormLabel>
                                        <Combobox as="div" value={selectedReward} onChange={setSelectedReward}>
                                            <Combobox.Button as="div">
                                                <Combobox.Input
                                                    className="w-full rounded-md border-0 bg-white py-2 pl-3 pr-12 text-gray-900 shadow-sm ring-1 ring-inset ring-[#E2E8F0] focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                                                    name="reward"
                                                    onChange={(event: any) => setQuery(event.target.value)}
                                                    placeholder="Select a Reward"
                                                    displayValue={(selectedReward: Reward) =>
                                                        selectedReward ? selectedReward.name : ""
                                                    }
                                                />
                                            </Combobox.Button>
                                            <Combobox.Options className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
                                                {rewardOptions.map(reward => (
                                                    <Combobox.Option
                                                        key={reward.id}
                                                        value={reward}
                                                        className={({ active }) =>
                                                            classNames(
                                                                "relative cursor-default select-none py-2 pl-3 pr-9",
                                                                active ? "bg-indigo-600 text-white" : "text-gray-900"
                                                            )
                                                        }
                                                    >
                                                        {({ active, selected }) => (
                                                            <>
                                                                <Box display={"flex"}>
                                                                    <Text
                                                                        as={"span"}
                                                                        className={classNames(
                                                                            "truncate",
                                                                            selected ? "font-semibold" : "font-normal"
                                                                        )}
                                                                    >
                                                                        {reward.name}
                                                                    </Text>
                                                                </Box>

                                                                {selected && (
                                                                    <Text
                                                                        as={"span"}
                                                                        className={classNames(
                                                                            "absolute inset-y-0 right-0 flex items-center pr-4",
                                                                            active ? "text-white" : "text-indigo-600"
                                                                        )}
                                                                    >
                                                                        <CheckIcon
                                                                            className="h-5 w-5"
                                                                            aria-hidden="true"
                                                                        />
                                                                    </Text>
                                                                )}
                                                            </>
                                                        )}
                                                    </Combobox.Option>
                                                ))}
                                                <Combobox.Option
                                                    value={""}
                                                    className={
                                                        "relative cursor-default select-none py-2 pl-3 pr-9 bg-indigo-100 hover:bg-indigo-600 hover:text-white text-gray-900"
                                                    }
                                                    onClick={onOpen}
                                                >
                                                    <Box
                                                        display={"flex"}
                                                        flexDirection={"row"}
                                                        gap={2}
                                                        alignItems={"center"}
                                                    >
                                                        <PlusIcon className="h-5 w-5" aria-hidden="true" />
                                                        <button>Create a Reward</button>
                                                    </Box>
                                                </Combobox.Option>
                                            </Combobox.Options>
                                        </Combobox>
                                    </Box>
                                    <ErrorMessage name="reward" component="p" className="mt-2 text-sm text-red-600" />
                                </FormControl>
                            </GridItem>
                            <GridItem colSpan={3}>
                                <Box display={"flex"} justifyContent="flex-end">
                                    <Button
                                        isLoading={isSubmitting}
                                        isDisabled={isSubmitting}
                                        type="submit"
                                        colorScheme="indigo"
                                        variant="solid"
                                    >
                                        Create Listing
                                    </Button>
                                </Box>
                            </GridItem>

正如我在上面提到的,问题是即使selectedMemory的内容和值发生变化,Yup也会不断抛出所需的错误.

推荐答案

Headless/UI文档真的很糟糕.所以我自己做了一些实验性的开发.

  • 我使用的是YUP,但我将seletedReward保持在一种状态中,我移除了那里的状态,而是在Formic中向字段添加了值、setFieldValue值(在我共享的代码之外),我开始使用Foric+Yup进行控制,并相应地更新了props .

  • 我开始将奖励作为YUP中的对象,而不是字符串,为此我更新了validationSchema,formValues内容.

在做完这些之后,它开始工作得很顺利,我希望它能帮助你解决问题.如果你有类似的问题,我愿意帮助你,如果你分享它作为一个 comments .

Typescript相关问答推荐

类型脚本不会推断键的值类型

在这种情况下,如何获得类型安全函数的返回值?

如何在TypeScrip面向对象程序设计中用方法/属性有条件地扩展类

在NextJS中获得Spotify Oauth,但不工作'

对于合并对象中的可选属性(例如选项),类型推断可能是错误的

适当限制泛型函数中的记录

类型脚本映射类型:从对象和字符串列表到键值对象

Angular 15使用react 式表单在数组内部创建动态表单数组

声明文件中的类型继承

缩小对象具有某一类型的任意字段的范围

抽象类对派生类强制不同的构造函数签名

是否将Angular *ngFor和*ngIf迁移到新的v17语法?

如何在Reaction 18、Reaction-Rout6中的导航栏中获取路由参数

TypeScrip:如何缩小具有联合类型属性的对象

如何扩展RxJS?

我可以将一个类型数组映射到TypeScrip中的另一个类型数组吗?

如何调整项目数组,但允许权重影响顺序

如何为字符串模板文字创建类型保护

将函数签名合并到重载中

类型string不可分配给类型string| 联盟| 的'