I am developing a custom DatePicker using the moment.js library in React. However, I have noticed that the value of my TextField is not updated when I select a new hour and minute in the DatePicker.
import clsx from "clsx";
import moment from "moment";
import React, { useCallback, useMemo } from "react";
import { WiTime3 } from "react-icons/wi";
import { Popover, PopoverContent, PopoverTrigger, Timer } from "../../atoms";
import { TextField } from "../../forms";
import { timeFormat } from "../../util/time-helpers";
export interface TimePickerFieldProps {
id: string;
name: string;
label?: string;
className?: string;
value?: moment.Moment;
onChange: (time: moment.Moment) => void;
onBlur?: () => void;
error?: string;
disabled?: boolean;
align?: "start" | "center" | "end";
}
export const TimePickerField = React.forwardRef<
HTMLInputElement,
TimePickerFieldProps
>(
(
{
id,
name,
onChange,
align,
className,
disabled,
error,
label,
onBlur,
value,
},
ref
) => {
const formattedValue = useMemo(
() => (value ? timeFormat(value) : ""),
[value]
);
const handleSelectTime = useCallback(
(time?: moment.Moment) => {
if (time) {
onChange(time);
}
},
[onChange]
);
const handleOpenChange = useCallback(
(open: boolean) => {
if (!open) {
onBlur?.();
}
},
[onBlur]
);
return (
<Popover onOpenChange={handleOpenChange}>
<PopoverTrigger className="block w-full">
<TextField
id={id}
name={name}
label={label}
autoComplete="off"
error={error}
disabled={disabled}
ref={ref}
readOnly
suffix={<WiTime3 className="text-primary" />}
className={clsx("pointer-events-none", className)}
value={formattedValue}
/>
</PopoverTrigger>
<PopoverContent align={align}>
<Timer selected={value} onSelect={handleSelectTime} />
</PopoverContent>
</Popover>
);
}
);
import moment from "moment";
import { useState } from "react";
import { HourBar } from "./HourBar/HourBar";
import { MinuteBar } from "./MinuteBar/MinuteBar";
export interface TimerProps {
selected?: moment.Moment | undefined;
onSelect?: (time: moment.Moment) => void;
}
export const Timer: React.FC<TimerProps> = ({ onSelect, selected }) => {
const [selectedTime, setSelectedTime] = useState<moment.Moment>(moment());
const handleTimeChange = (field: "hour" | "minute", value: number) => {
setSelectedTime((prevTime) => prevTime.clone().set(field, value));
};
return (
<div>
<div className="flex flex-row h-[7.75rem] w-[6.5rem] bg-other-transparent-darkest rounded p-2 gap-2">
<HourBar
selectedHour={selectedTime.hour()}
onHourChange={handleTimeChange}
/>
<MinuteBar
selectedMinute={selectedTime.minute()}
onMinuteChange={handleTimeChange}
/>
</div>
</div>
);
};
import { Caption } from "../../../typography";
export interface HourBarProps {
selectedHour: number;
onHourChange: (field: "hour" | "minute", value: number) => void;
}
export const HourBar: React.FC<HourBarProps> = ({
selectedHour,
onHourChange,
}) => {
const hours = Array.from({ length: 24 }, (_, i) => i);
return (
<div className="flex flex-col overflow-y-auto scrollbar-hide w-full items-center gap-1">
{hours.map((hour, index) => (
<Caption
key={index}
className={`flex justify-center rounded py-[0.125rem] size-full text-sm cursor-pointer
${hour === selectedHour && "bg-primary text-font-primary"}`}
onClick={() => onHourChange("hour", hour)}
>
{hour}
</Caption>
))}
</div>
);
};
import { Caption } from "../../../typography";
export interface HourBarProps {
selectedMinute: number;
onMinuteChange: (field: "hour" | "minute", value: number) => void;
}
export const MinuteBar: React.FC<HourBarProps> = ({
selectedMinute,
onMinuteChange,
}) => {
const minutes = Array.from({ length: 60 }, (_, i) => i);
const filteredMinutes = minutes.filter((minute) => minute % 15 === 0);
return (
<div className="flex flex-col overflow-y-auto scrollbar-hide w-full items-center gap-1">
{filteredMinutes.map((minute, index) => (
<Caption
key={index}
className={`flex justify-center rounded py-[0.125rem] size-full text-sm cursor-pointer
${minute === selectedMinute && "bg-primary text-font-primary"}`}
onClick={() => onMinuteChange("minute", minute)}
>
{minute}
</Caption>
))}
</div>
);
};
**Consultation: ** What could be causing the TextField value to not update correctly when selecting a new hour and minute in the DatePicker? Are there any additional steps I need to take to ensure the value is updated correctly in the UI?
Any suggestions or help would be greatly appreciated! Thank you very much in advance. When I select a new hour and minutes the value of the TextField is not updating