0

I am fairly new to React (but have coded in JavaScript and C# for 20 plus years). I have a vanilla form using hook-form, react-bootstrap, zod and flowbite-react. There are two nearly identical functions: create and update. The create function works correctly, but the update form incorrectly validates the two required inputs. The first time the submit button is selected, I get validation errors on both required inputs; the second time just the second required input and the third time it works and the update is sent back to the server. Both input controls have text in them.


export const MembershipUpdate = () => {
    const [membership, setMembership] = useState(
        {
            id: 0,
            firstName: '',
            lastName: '',
            fullName: '',
            shortname: '',
            nickName: '',
            wheelchair: false
        }
    );
    const location = useLocation();
    const id: number = location.state;

    const {
        register,
        handleSubmit,
        formState: { errors },
        
    } = useForm<UpdateFormData>({
        resolver: zodResolver(UpdateFormDataSchema),
    });

    const onSubmit: SubmitHandler<UpdateFormData> = (data) =>updateData(data) // send updated record to server

    const navigate = useNavigate();
    
    function OnChange(e: React.ChangeEvent<HTMLInputElement>) {
        setMembership({ ...membership, [e.target.name]: e.target.value });
    }

    function OnChecked(e: React.ChangeEvent<HTMLInputElement>) {
        setMembership({ ...membership, [e.target.name]: e.target.checked });
    }
    
    useEffect(() => {
        GetData(); // get original record from server
    }, []);

    const contents = membership === undefined
        ? <p><em>Loading ...</em></p> :

        <form onSubmit={handleSubmit(onSubmit)} >
            <input type="hidden" {...register("id", { valueAsNumber: true })} value={membership.id} />
            <TextInput {...register("nickName")} type="hidden" />
            <TextInput {...register("fullName")} type="hidden" />
            <Container >
                <Row>
                    <Col style={{ width: '15%' }}><Label>First Name:</Label></Col>
                    <Col><TextInput type="text" {...register('firstName')} style={{ width: '85%' }} value={membership.firstName}  onChange={OnChange} /></Col>
                </Row>
                <Row>
                    <Col style={{ width: '15%' }}><Label>Last Name:</Label></Col>
                    <Col><TextInput  {...register('lastName')} style={{ width: '85%' }} value={membership.lastName} onChange={OnChange} /></Col>
                </Row>
                <Row>
                    <Col style={{ width: '15%' }}><Label>Short Name:</Label></Col>
                    <Col><TextInput {...register('shortname')} style={{ width: '85%' }} value={membership.shortname} onChange={OnChange} /></Col>
                </Row>
                <Row>
                    <Col style={{ width: '15%' }}><Label>Wheel Chair:</Label></Col>
                    <Col style={{ textAlign: "left", width: '85%' }}>
                        <Checkbox {...register('wheelchair')}checked={membership.wheelchair} onChange={OnChecked} /></Col>
                </Row>
                <Row>
                    <Col style={{ textAlign: "center", width: '100%' }}>
                        <TextInput type="submit" />
                    </Col>
                </Row>
                {errors.firstName && <p className="errorMessage">{errors.firstName.message}</p>}
                {errors.lastName && <p className="errorMessage">{errors.lastName.message}</p>}
                {errors.shortname && <p className="errorMessage">{errors.shortname.message}</p>}
            </Container>
        </form>
    
    return (
        <>
        <h1>Update record</h1>
            {contents}

            
        </>
        );
}

The schema and data format is defined as:

import { z } from 'zod';
export const UpdateFormDataSchema = z.object({
    id: z.number(),
    firstName: z.string().min(1, "First Name is required").max(50, "First Nmme has a maximum of 50 characters"),
    lastName: z.string().min(1, "Last Name is required").max(50, "Last Nmme has a maximum of 50 characters"),
    fullName: z.string(), // computed column in DB
    shortname: z.string().max(25, "Short Nmme has a maximum of 25 characters"),
    nickName: z.string(), //computed column in DB
    wheelchair: z.boolean()
});

export type UpdateFormData = z.infer<typeof UpdateFormDataSchema>;

Screen shot of the update page

1 Answer 1

0

I am fairly new to React (but have coded in JavaScript and C# for 20 plus years). I have a vanilla form using hook-form, react-bootstrap. There are two nearly identical functions: create and update. The create function works correctly, but the update form incorrectly validates the two required inputs. The first time the submit button is selected, I get validation errors on both required inputs; the second time just the second required input and the third time it works and the update is sent back to the server. But if I alter an input, the validation error is gone.

const MembershipUpdate = () => {
    const [membership, setMembership] = useState(
        {
            id: 0,
            firstName: '',
            lastName: '',
            fullName: '',
            shortname: '',
            nickName: '',
            wheelchair: false
        }
    );
    const location = useLocation();
    const id: number = location.state;

    const { register, handleSubmit, formState: { errors } } = useForm<IMembership>()

    const onSubmit: SubmitHandler<IMembership> = (data) => updateData(data)

    const navigate = useNavigate();




    useEffect(() => {
        GetData();
        setMembership({ ...membership, [id]: id });
    }, []);

    function OnChange(e: React.ChangeEvent<HTMLInputElement>) {
        setMembership({ ...membership, [e.target.name]: e.target.value });
    }

    function OnChecked(e: React.ChangeEvent<HTMLInputElement>) {
        setMembership({ ...membership, [e.target.name]: e.target.checked });
    }

    return (
        <>
            <p>ID: {membership.id}</p>
            <form onSubmit={handleSubmit(onSubmit)} >


                <Container >
                    <input {...register("id")} type="hidden" value={membership.id} />
                    <input {...register("nickName")} type="hidden" value={membership.nickName} />
                    <input {...register("fullName")} type="hidden" value={membership.fullName} />
                    <Row>
                        <Col><label>First Name:</label></Col>

                        <Col><input type="text" {...register('firstName', {
                            required: true,
                            maxLength: 50

                        })} value={membership.firstName} title="firstName" placeholder=""
                            onChange={OnChange} style={{ width: '350px' }} />
                            {errors.firstName && errors.firstName.type === "required" && (
                                <p>This is required</p>
                            )}
                            {errors.firstName && errors.firstName.type === "maxLength" && (
                                <p>Max length exceeded</p>
                            )}
                            {!errors.firstName && (
                                <p></p>
                            )}
                        </Col>
                    </Row>
                    <Row>
                        <Col><label>Last Name:</label></Col>

                        <Col><input type="text" {...register('lastName', {
                            required: true,
                            maxLength: 50
                        })} value={membership.lastName} title="lastName" placeholder=""
                            style={{ width: '350px' }}
                            onChange={OnChange} />
                            {errors.lastName && errors.lastName.type === "required" && (
                                <p>This is required</p>
                            )}
                            {errors.lastName && errors.lastName.type === "maxLength" && (
                                <p>Max length exceeded</p>
                            )}
                            {!errors.lastName && (
                                <p></p>
                            )}
                        </Col>
                    </Row>
                    <Row>
                        <Col><label>Short Name:</label></Col>

                        <Col><input type="text" {...register('shortname', {
                            maxLength: 25
                        })} value={membership.shortname} title="shortname" placeholder=""
                            style={{ width: '350px' }}
                            onChange={OnChange} />

                            {errors.lastName && errors.lastName.type === "maxLength" && (
                                <p>Max length exceeded</p>
                            )}
                            {!errors.shortname && (
                                <p></p>
                            )}

                        </Col>
                    </Row>
                    <Row>
                        <Col><label>Wheel Chair:</label></Col>

                        <Col style={{ textAlign: "left" }}>
                            <input type="checkbox" {...register('wheelchair')}
                                title="wheelchair" placeholder=""
                                checked={membership.wheelchair}
                                onChange={OnChecked} /></Col>
                    </Row>
                    <Row>
                        <Col >
                            <input type="submit" />
                        </Col>
                    </Row>


                </Container>
            </form>
        </>
    );
}

Here is a screen shot:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.