React-Datepicker与Formik集成时时间时区差2小时问题求助
问题分析与解决方案
你的问题出在两个核心点:一是React-Datepicker未与Formik的表单状态正确绑定,导致提交的可能还是初始时间;二是Date对象被JSON序列化时会自动转为UTC时区格式,和你选中的本地时区时间产生偏移。
1. 修复表单绑定问题
你当前用独立的useState管理startDate,但Formik的values.time并没有同步更新选择结果。正确做法是让DatePicker直接关联Formik的表单状态,无需额外维护独立state:
import DatePicker, { registerLocale } from 'react-datepicker'; import { uk } from 'date-fns/locale/uk'; import { Formik, Field, Form, useFormikContext } from 'formik'; import React from 'react'; import { format } from 'date-fns'; // 引入date-fns格式化工具 // 封装适配Formik的DatePicker组件 const FormikDatePicker = ({ ...props }) => { const { setFieldValue } = useFormikContext(); return ( <DatePicker {...props} onChange={(date) => setFieldValue(props.name, date)} /> ); }; export const Time = () => { registerLocale('uk', uk); return ( <Formik initialValues={{ time: new Date() }} onSubmit={async (values) => { await new Promise(resolve => setTimeout(resolve, 500)); // 格式化选中的时间为本地时区格式,避免UTC偏移 const formattedTime = format(values.time, "yyyy-MM-dd'T'HH:mm:ssXXX"); alert(JSON.stringify({ time: formattedTime }, null, 2)); // 若仅需时间部分,可改为 format(values.time, "H:mm") }} > <Form> <Field name="time" component={FormikDatePicker} locale="uk" showTimeSelect showTimeSelectOnly timeIntervals={30} timeCaption="Time" dateFormat="H:mm" /> <button type="submit">Save</button> </Form> </Formik> ); };
2. 处理时区偏移问题
直接JSON.stringifyDate对象时,会自动转换为UTC时区的ISO字符串(比如你选中的GMT+0200 13:00会变成UTC 11:00的格式)。要得到与选中一致的时间,需:
- 用
date-fns的format函数,将Date对象格式化为本地时区的字符串,示例中用的"yyyy-MM-dd'T'HH:mm:ssXXX"会保留时区信息,确保时间与选择一致。 - 若仅需时分部分,直接使用
format(values.time, "H:mm")即可。
关键说明
- 通过
useFormikContext获取setFieldValue,让DatePicker的选择直接同步到Formik的values.time,避免状态不一致问题。 - 提交时不要直接序列化Date对象,先通过date-fns格式化后再处理,彻底解决时区偏移问题。
内容的提问来源于stack exchange,提问作者OleksandrShar
相关产品推荐
相关产品推荐

