React Hook Form + Material UI Datepickers 和 Luxon 输出格式

Bra*_*ute 5 material-ui luxon react-hook-form

我正在开发一个 React 应用程序,使用 React Hook Form、Material UI 和 Luxon 进行日期解析。

我已经制作了许多可重用的表单字段,并且一切都很好,但在 DatePickers 和输出格式方面遇到了一些麻烦。

基本上,我想获取输出的 DatePicker 和 TimePicker 的值并正确格式化它以发送到后端。

我有以下组件:

日期选择器:

import React from "react";
import PropTypes from "prop-types";
import {Controller, useFormContext} from "react-hook-form";
import DatePicker from '@mui/lab/DatePicker';
import DateAdapter from '@mui/lab/AdapterLuxon';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import TextInput from "../TextInput/TextInput";

export const DATE_INPUT_FORMAT = "MM/dd/yyyy";

export const DateInput = ({name, label, defaultValue, ...props}) => {
    const {control, register, formState: {errors}} = useFormContext();
    return (
        <Controller
            name={name}
            control={control}
            render={({field}) => (
                <LocalizationProvider dateAdapter={DateAdapter}>
                    <DatePicker
                        {...field}
                        inputFormat={DATE_INPUT_FORMAT}
                        renderInput={(props) => (
                            <TextInput
                                label={label}
                                defaultValue={defaultValue}
                                {...register(name)}
                                error={!!errors[name]}
                                helperText={errors[name] ? errors[name]?.message : ''}
                                {...props}
                            />
                        )}
                        {...props}
                    />
                </LocalizationProvider>
            )}
        />
    )
};

DateInput.propTypes = {
    name: PropTypes.string.isRequired,
    label: PropTypes.string,
    defaultValue: PropTypes.string
};

DateInput.defaultProps = {
    label: "",
    defaultValue: "",
};

export default DateInput;
Run Code Online (Sandbox Code Playgroud)

和时间选择器:

import React from "react";
import PropTypes from "prop-types";
import {Controller, useFormContext} from "react-hook-form";
import TimePicker from '@mui/lab/TimePicker';
import DateAdapter from '@mui/lab/AdapterLuxon';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import TextInput from "../TextInput/TextInput";

export const TIME_INPUT_FORMAT = "hh:mm a";

export const TimeInput = ({name, label, defaultValue, ...props}) => {
    const {control, register, formState: {errors}} = useFormContext();
    return (
        <Controller
            name={name}
            control={control}
            render={({field}) => (
                <LocalizationProvider dateAdapter={DateAdapter}>
                    <TimePicker
                        {...field}
                        inputFormat={TIME_INPUT_FORMAT}
                        renderInput={(props) => (
                            <TextInput
                                label={label}
                                defaultValue={defaultValue}
                                {...register(name)}
                                error={!!errors[name]}
                                helperText={errors[name] ? errors[name]?.message : ''}
                                {...props}
                            />
                        )}
                        {...props}
                    />
                </LocalizationProvider>
            )}
        />
    )
};

TimeInput.propTypes = {
    name: PropTypes.string.isRequired,
    label: PropTypes.string,
    defaultValue: PropTypes.string
};

TimeInput.defaultProps = {
    label: "",
    defaultValue: "",
};

export default TimeInput;
Run Code Online (Sandbox Code Playgroud)

两者都使用 Luxon 作为 dateAdpater。该表单运行良好,并且值更新良好。但是,在处理 onSubmit 时,我正在读取表单值并将它们发送回后端,并且我的 DatePicker 和 TimePicker 以以下格式返回它们的值:

日期:“2021 年 11 月 13 日星期六 23:36:59 GMT-0500(东部标准时间)”

时间:“2021-11-02T18:30:03.317-04:00”

其中日期正确设置为日期,时间正确设置为时间。我假设读取 UI 上的值所产生的值将以 Luxon 日期格式返回,或者至少可以轻松解析为 Luxon 日期格式。这样我就可以将它们组合并格式化为日期时间字符串,以便数据库能够接受它们。

我知道我可以手动解析日期字符串,但我认为必须有更好的方法来做到这一点。然而,我已经在 Luxon 和 MUI 文档中搜索了几个小时,但没有任何运气。

任何对此的帮助将不胜感激。

举个例子:

我采用两个表单值并将它们传递到一个函数中,例如:

export const formatDateAndTimeToDatetimeField = (date, time) => {
    const dateParsed = {Something here};
    const timeParsed = {Something here};
    const datetime = Datetime.fromObject({
        year: dateParsed.year,
        month: dateParsed.month,
        day: dateParsed.day,
        hour: timeParsed.hour,
        minute: timeParsed.minute,
    });
    return datetime.toUTC().toFormat("yyyy-MM-dd hh:mm:ss+00:00");
}
Run Code Online (Sandbox Code Playgroud)

如果不编写代码来显式解析字符串,我就无法完全弄清楚{Something here}。我认为 Luxon 一定有一个更强大/更简单的解决方案,但我在任何地方都找不到它

感谢您提前提供的任何帮助。

小智 0

你好,是的,有一个更好的方法来解析字符串,我也对 MUI 如何处理 DateTime 输入感到困惑。
事实上,一旦您date在表单中获取了 as 字符串,然后将其提交到后端,您就可以使用 luxon 解析该字符串以获取完整的 DateTime 对象并应用您想要的所有格式。

import {DateTime} from 'luxon';


const Submit = (data) => {
   const date = DateTime.fromISO(data.date);
   // now you can use date object like a normal luxon DT object
   const payload = date.toSQLDate()
   // here request your backend with the payload
}
Run Code Online (Sandbox Code Playgroud)

我的 DatePicker 组件如下所示:

import React from 'react';
import { useController } from 'react-hook-form';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DatePicker as MuiDatePicker } from '@mui/x-date-pickers/DatePicker';
import MuiTextField from '@mui/material/TextField';
import { AdapterLuxon } from '@mui/x-date-pickers/AdapterLuxon';

const DatePicker = ({ label, control, name, renderInput, inputFormat }) => {
  const {
    field: { onChange, value },
  } = useController({ control, name, defaultValue: '' });

  const changeHandler = (value) => {
    onChange(value.toISO());
  };

  const renderInputDefault = (props) => <MuiTextField {...props} />;
  return (
    <LocalizationProvider dateAdapter={AdapterLuxon}>
      <MuiDatePicker
        value={value}
        onChange={changeHandler}
        renderInput={renderInput ? renderInput : renderInputDefault}
        label={label}
        disableMaskedInput
        inputFormat={inputFormat}
      />
    </LocalizationProvider>
  );
};
Run Code Online (Sandbox Code Playgroud)

希望它会有所帮助:)