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

React+Antd项目刷新后恢复Datepicker值报date.locale错误

问题描述

使用React + Antd开发项目时,选择Antd DatePicker的日期能正常更新SessionStorage,但页面刷新后,其他表单域能从SessionStorage恢复数据,唯独DatePicker抛出错误:

date.locale is not a function at Object.format (dayjs.js:185:19)

错误截图
ERROR

SessionStorage中的日期值
Session Storage

父组件 Navigation.tsx

import HotelAndDate from "./HotelAndDate";
import { Steps, message, Form } from 'antd'
import Button from 'antd/es/button';
import RoomDetails from "./RoomDetails";
import Payment from "./Payment";
import './index.css'
import { useNavigation } from "./useNavigation";
import { useEffect, useState } from "react";
import { useSessionStorage } from "./useSessionStorage";
import * as dayjs from 'dayjs'
dayjs().format()

export type FormT = {
    hotel_name: string
    startDate: string
    endDate: string
    parents: number
    children: number
}


const initialData: FormT = JSON.parse(sessionStorage.getItem('formData') || '{}') || {
    hotel_name: '',
    startDate: '2022-12-22',
    endDate: '',
    parents: 0,
    children: 0
};


function Navigation() {
    const [data, setData] = useSessionStorage<FormT[] | FormT>('formData', initialData);
    const [form] = Form.useForm();
    useEffect(() => {
        let storedData = JSON.parse(sessionStorage.getItem('formData') || '{}');
        setData(storedData);
    }, []);
    console.log('SSS', data);


    const onFinish = async () => {
        const values = await form.validateFields();
        console.log(values);
    }


    var INITIAL_STEPS = [
        {
            title: 'Hotel And Date',
            content: <HotelAndDate data={data} setData={setData} updateFields={updateForm} />,
        },
        {
            title: 'Room Details',
            content: <RoomDetails />,
        },
        {
            title: 'Payment',
            content: <Payment />,
        },
    ];

    const { current, step, steps, next, prev, goTo, isFirstStep, isLastStep } = useNavigation(INITIAL_STEPS)
    const items = steps.map((item) => ({ key: item.title, title: item.title }));

    function updateForm(fields: Partial<FormT>): void {
        setData(prev => {
            return { ...prev, ...fields }
        })
    }

    function handlePreviousClick() {
        prev();
    }

    return (
        <div className=" mx-auto flex max-w-7xl  p-6 lg:px-8" style={{ flexDirection: 'column', rowGap: '2rem' }}>
            <Steps current={current} items={items} labelPlacement='vertical'></Steps>
            <Form layout="vertical" initialValues={initialData} onFinish={onFinish} >
                {steps[current].content}
            </Form>
            <div className="flex items-center justify-between">
                {!isFirstStep && (
                    <Button type="primary" htmlType="button" onClick={handlePreviousClick}> Previous</Button>
                )}
                {current < steps.length - 1 && (
                    <Button type="primary" htmlType="button" onClick={next}>Next</Button>
                )}
                {isLastStep && (
                    <Button type="primary" htmlType="submit" onClick={() => message.success('Processing complete!')}>
                        Done
                    </Button>
                )}
            </div>
        </div>
    )
}

export default Navigation

子组件 HotelAndDate.tsx(问题出现位置)

function HotelAndDate({ data, setData, updateFields }: { data: any, setData: any, updateFields: any }) {
  const { hotelListLoading, hotels } = useGetHotelList();
  return (
    <Row gutter={[32, 32]} justify="space-between">
     {/* other form areas */}
      <Col >
        <Form.Item name="startDate" label="Start Date" rules={[{ required: true }]}>
          <DatePicker  value={dayjs("")} onChange={(date,dateString) => date && updateFields({ startDate:  dateString})} placeholder="Start Date" />
        </Form.Item>
      </Col>
     {/* other form areas */}
    </Row>
  )
}

export default HotelAndDate;
解决方案

这个错误的核心原因是:Antd的DatePicker期望接收dayjs实例对象,但从SessionStorage读取的是字符串格式的日期,直接传给DatePicker会导致内部调用dayjs方法时出错。

1. 初始化表单时转换日期字符串为dayjs实例

修改父组件中initialData的初始化逻辑,把从SessionStorage读取的日期字符串转换成dayjs实例:

const storedRaw = sessionStorage.getItem('formData') || '{}';
const storedData = JSON.parse(storedRaw);
const initialData: FormT = {
    hotel_name: '',
    startDate: '2022-12-22',
    endDate: '',
    parents: 0,
    children: 0,
    ...storedData,
    // 转换日期字符串为dayjs实例
    startDate: storedData.startDate ? dayjs(storedData.startDate) : dayjs('2022-12-22'),
    endDate: storedData.endDate ? dayjs(storedData.endDate) : dayjs('')
};

2. 修正DatePicker的value绑定

子组件里的DatePicker不要硬写固定值,应该从父组件传递的data中取对应值,同时确保是dayjs实例:

// HotelAndDate.tsx
<Form.Item name="startDate" label="Start Date" rules={[{ required: true }]}>
  <DatePicker 
    value={data.startDate ? dayjs(data.startDate) : dayjs('')} 
    onChange={(date, dateString) => date && updateFields({ startDate: dateString })} 
    placeholder="Start Date" 
  />
</Form.Item>

3. 优化冗余逻辑

父组件中的useEffect属于冗余逻辑,因为useSessionStorage本身已经处理了从SessionStorage读取初始值的逻辑,可以直接删除该useEffect,避免重复设置数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:42:58