【问题标题】:First form values get lost if the input unmounts in react-hook-form如果输入在 react-hook-form 中卸载,第一个表单值会丢失
【发布时间】:2021-05-27 17:10:27
【问题描述】:

我将一份表格分成两部分。第一种形式采用 firstName、lastName 和 profilePhoto。第二个表单接受电子邮件、密码、confirmPassword 等。当用户填写第一个表单并单击下一步按钮时,第一个表单中的值不会停留在表单状态。如 react-hook-form 文档中所述,我已将 shouldUnregister 设置为 false。但这似乎并不能解决我的问题。

//hooks.ts


 const defaultRegisterValues = {
            email: "",
            password: "",
            confirmPassword: "",
            firstName: "",
            lastName: "",
            institution: "",
            regNo: "",
            department: "",
            profilePhoto: "",
        };

        const {
            register,
            handleSubmit,
            watch,
            getValues,
            formState: { errors: formErrors },
        } = useForm<RegisterFormInputs>({
            defaultValues: defaultRegisterValues,
            shouldFocusError: true,
            shouldUnregister: false,
        });

        const watchFields = watch();
        console.log("fields", watchFields);

        const emailRegister = register("email", {
            required: true,
            minLength: 5,
            maxLength: 50,
        });
        const passwordRegister = register("password", {
            required: true,
            minLength: 5,
            maxLength: 50,
        });
        const confirmPasswordRegister = register("confirmPassword", {
            required: true,
            minLength: 5,
            maxLength: 50,
            validate: value => value === watch("password") || "Passwords do not match",
        });
        const firstNameRegister = register("firstName", {
            required: true,
            maxLength: 50,
        });
        const lastNameRegister = register("lastName", {
            maxLength: 50,
        });

        const institutionRegister = register("institution", {
            required: true,
        });

        const departmentRegister = register("department", {
            required: true,
        });
        const regNoRegister = register("regNo", {
            required: true,
            minLength: 5,
            maxLength: 15,
        });
        const profilePhotoRegister = register("profilePhoto", {
            required: true,
        });

        const onSubmit = handleSubmit((data: RegisterFormInputs) => {
            console.log("submitting");
            console.log("Creating user...", data);
        });
      
      //FirstForm.tsx
      const { firstNameRegister, lastNameRegister, profilePhotoRegister, errors, getValues } = useRegister();
        return (
            <Slide
                direction="left"
                in={!isOpen}
                style={{ zIndex: 5, width: "30vw", position: "relative" }}
                unmountOnExit={true}
            >
                <FormControl isInvalid={!!errors.profilePhoto} isRequired>
                    <FileUpload accept={"image/*"} multiple={false} register={profilePhotoRegister}>
                        <IconButton
                            aria-label="Profile Photo"
                            icon={<AvatarPlaceholder boxSize={120} />}
                            isRound
                            boxSize={120}
                            style={{ margin: "0 auto" }}
                        />
                    </FileUpload>
                    <FormErrorMessage>{errors.profilePhoto && errors.profilePhoto}</FormErrorMessage>
                </FormControl>
                <RegisterFieldContainer>
                    <FormControl id="firstName" isInvalid={!!errors.firstName}>
                        <FormLabel>First Name</FormLabel>
                        <Input
                            name={firstNameRegister?.name}
                            type="text"
                            ref={firstNameRegister?.ref}
                            onChange={firstNameRegister?.onChange}
                            defaultValue={getValues("firstName")}
                        />
                        <FormErrorMessage>{errors.firstName}</FormErrorMessage>
                    </FormControl>
                    <FormControl id="lastName" isInvalid={!!errors.lastName}>
                        <FormLabel>Last Name</FormLabel>
                        <Input
                            name={lastNameRegister?.name}
                            type="text"
                            ref={lastNameRegister?.ref}
                            onChange={lastNameRegister?.onChange}
                            defaultValue={getValues("lastName")}
                        />
                        <FormErrorMessage>{errors.lastName}</FormErrorMessage>
                    </FormControl>
                </RegisterFieldContainer>
                <Center>
                    <IconButton
                        variant="solid"
                        aria-label="forward"
                        icon={<ArrowForwardIcon boxSize={10} />}
                        isRound
                        boxSize={16}
                        marginTop={10}
                        onClick={onToggle}
                    />
                </Center>
            </Slide>
        
        
        // SecondForm.tsx
        const {
            emailRegister,
            passwordRegister,
            confirmPasswordRegister,
            regNoRegister,
            institutionRegister,
            departmentRegister,
            errors,
        } = useRegister();
        return (
            <Slide
                in={isOpen}
                unmountOnExit={true}
                direction="right"
                style={{ zIndex: zIdxValue, width: "30vw", position: "relative" }}
            >
                <RegisterFieldSubContainer>
                    <FormControl id="email">
                        <FormLabel>Email</FormLabel>
                        <Input name={emailRegister?.name} type="email" ref={emailRegister?.ref} onChange={emailRegister?.onChange} />
                        {errors.email && <FormErrorMessage>{errors.email}</FormErrorMessage>}
                    </FormControl>
                    <FormControl id="regNo">
                        <FormLabel>Registration Number</FormLabel>
                        <Input name={regNoRegister?.name} type="text" ref={regNoRegister?.ref} onChange={regNoRegister?.onChange} />
                        {errors.regNo && <FormErrorMessage>{errors.regNo}</FormErrorMessage>}
                    </FormControl>
                </RegisterFieldSubContainer>
                <RegisterFieldSubContainer>
                    <FormControl id="password">
                        <FormLabel>Password</FormLabel>
                        <Input
                            name={passwordRegister?.name}
                            type="password"
                            ref={passwordRegister?.ref}
                            onChange={passwordRegister?.onChange}
                        />
                        {errors.password && <FormErrorMessage>{errors.password}</FormErrorMessage>}
                    </FormControl>
                    <FormControl id="confirmPassword">
                        <FormLabel>Confirm Password</FormLabel>
                        <Input
                            name={confirmPasswordRegister?.name}
                            type="password"
                            ref={confirmPasswordRegister?.ref}
                            onChange={confirmPasswordRegister?.onChange}
                        />
                        {errors.confirmPassword && <FormErrorMessage>{errors.confirmPassword}</FormErrorMessage>}
                    </FormControl>
                </RegisterFieldSubContainer>
                <RegisterFieldSubContainer>
                    <FormControl id="institution">
                        <FormLabel>Institution</FormLabel>
                        <Input
                            name={institutionRegister?.name}
                            type="text"
                            ref={institutionRegister?.ref}
                            onChange={institutionRegister?.onChange}
                        />
                        {errors.institution && <FormErrorMessage>{errors.institution}</FormErrorMessage>}
                    </FormControl>
                    <FormControl id="department">
                        <FormLabel>Department</FormLabel>
                        <Input
                            name={departmentRegister?.name}
                            type="text"
                            ref={departmentRegister?.ref}
                            onChange={departmentRegister?.onChange}
                        />
                        {errors.department && <FormErrorMessage>{errors.department}</FormErrorMessage>}
                    </FormControl>
                </RegisterFieldSubContainer>
                <Flex flexDirection="row" alignItems="baseline" width="100%" justifyContent="space-between">
                    <Button variant="link" onClick={onToggle} marginTop="2em">
                        Back
                    </Button>
                    <RegisterButton type="submit" variant="solid" marginTop="2em" width="45%">
                        Register
                    </RegisterButton>
                </Flex>
            </Slide>
      
      //index.tsx (the one that renders both forms
      const { handleSubmit } = useRegister();
        return (
            <RegisterContainer>
                <RegisterFormContainer>
                    <Heading>Register</Heading>
                    <RegisterForm onSubmit={handleSubmit}>
                        <FirstForm isOpen={isOpen} onToggle={onToggle} />
                        <SecondForm isOpen={isOpen} onToggle={onToggle} />
                    </RegisterForm>
                    {!isOpen && <Link href="/login">Already have an account? Login</Link>}
                </RegisterFormContainer>
            </RegisterContainer>
        );
      

【问题讨论】:

    标签: javascript reactjs typescript react-hook-form


    【解决方案1】:

    我相信您有两个独立的组件,并在每个组件中导入和实例化 useRegister()。这样你就有了两个独立的表单状态。

    我建议您为这两个组件创建一个共同的父级。在那里实例化 useRegister() 一次并将 desctructured 的道具传递给当前步骤的表单。

    【讨论】:

    • 我也做过同样的事情。 FirstForm 和 SecondForm 有一个父组件。问题是当我点击进入下一个表单时,第一个表单必须卸载。这会导致值消失。
    • 您可以在 stackblitz.com 或 codesandbox.io 上发帖 minimal reproducible example 吗?
    猜你喜欢
    • 2022-11-12
    • 1970-01-01
    • 2020-06-06
    • 2023-03-17
    • 2020-06-02
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多