You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-datepicker日期对象未保存,MERN项目react-hook-form问题咨询

Troubleshooting the 400 Error & React Hook Form Refactor

Hey there! Let's break down why you're hitting that "dateOfBirth is required" 400 error, then refactor your code to align with react-hook-form's core design (no more redundant state!).

Why the 400 Error Happens

Your DatePicker isn't registered with react-hook-form at all—so when you submit the form, that field never gets included in the form data. On top of that, your manual date state is causing sync issues:

  • You have two duplicate useEffect calls fetching the same member data, which can lead to date and member.dateOfBirth being out of sync (one's a timestamp, the other's a raw string).
  • If the user doesn't modify the date, you're sending whatever date was set to initially—maybe a null value or a format your backend doesn't recognize, triggering the required field validation.

Refactored Code (No More Custom State!)

We'll ditch your custom state entirely and let react-hook-form handle everything, including the third-party DatePicker using the Controller component (built for non-standard inputs):

import { useForm, Controller } from "react-hook-form";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import axios from "axios";
import { useEffect } from "react";

export default function EditMember(props) {
  // Initialize react-hook-form with empty default values
  const { register, handleSubmit, control, setValue } = useForm({
    defaultValues: {
      firstName: "",
      lastName: "",
      dateOfBirth: null,
      gender: "",
      address: "",
      phoneNumber: ""
    }
  });

  // Fetch member data ONCE and populate form fields
  useEffect(() => {
    const fetchMember = async () => {
      try {
        const res = await axios.get(`http://localhost:5000/members/${props.match.params.id}`);
        // Use setValue to populate each form field with fetched data
        setValue("firstName", res.data.firstName);
        setValue("lastName", res.data.lastName);
        // Convert backend's date string to a Date object for the DatePicker
        setValue("dateOfBirth", new Date(res.data.dateOfBirth));
        setValue("gender", res.data.gender);
        setValue("address", res.data.address);
        setValue("phoneNumber", res.data.phoneNumber);
      } catch (err) {
        console.error("Failed to load member data:", err);
      }
    };

    fetchMember();
  }, [props.match.params.id, setValue]);

  const onSubmitData = async (data) => {
    try {
      // Format the date to match what your backend expects (adjust as needed)
      const updatedMember = {
        ...data,
        dateOfBirth: data.dateOfBirth ? data.dateOfBirth.toISOString() : null
      };
      const res = await axios.post(
        `http://localhost:5000/members/update/${props.match.params.id}`,
        updatedMember
      );
      console.log("Member updated successfully:", res.data);
    } catch (err) {
      console.error("Failed to update member:", err);
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmitData)}>
      <div>
        {/* Use the spread operator for cleaner register syntax */}
        <input
          type="text"
          placeholder="First name"
          {...register("firstName")}
        />
        <input
          type="text"
          placeholder="Last name"
          {...register("lastName")}
        />
        
        <span>Male</span>
        <input
          type="radio"
          value="Male"
          {...register("gender")}
        />
        <span>Female</span>
        <input
          type="radio"
          value="Female"
          {...register("gender")}
        />
        
        <input
          type="text"
          placeholder="Address"
          {...register("address")}
        />
        <input
          type="text"
          placeholder="Phone Number"
          {...register("phoneNumber")}
        />

        {/* Wrap DatePicker with Controller to integrate with react-hook-form */}
        <Controller
          name="dateOfBirth"
          control={control}
          render={({ field }) => (
            <DatePicker
              selected={field.value}
              onChange={field.onChange}
              placeholderText="Select date"
            />
          )}
        />

        <button type="submit">Edit Log</button>
      </div>
    </form>
  );
}

Key Improvements:

  • No more custom state: All form data is managed by react-hook-form, eliminating sync issues.
  • Single data fetch: Merged duplicate useEffect calls into one async function to avoid redundant API requests.
  • Controller for DatePicker: Properly integrates the third-party date picker with react-hook-form's state management.
  • Cleaner registration: Used {...register("fieldName")} instead of ref={register} (the recommended syntax for react-hook-form).
  • Date formatting: Converts the Date object to an ISO string (adjust this if your backend expects a different format like YYYY-MM-DD).

内容的提问来源于stack exchange,提问作者fernando91

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 21:17:46