I am passing a plain date as string from api, something like 2022-04-24, but on front react, it is parsing the date to the local timezone, which I don't want to be parsed to local timezone. My code on react looks like:
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from "#hookform/resolvers/yup";
import * as Yup from "yup";
import ReactDatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
export function App() {
const schema = Yup.object({});
const {
register,
handleSubmit,
formState: { errors },
control
} = useForm({
resolver: yupResolver(schema)
});
const onSubmit = async (input) => {
console.log("input", input);
};
const item = {
id: 12,
release_date: "2022-04-24"
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
control={control}
name="release_date"
defaultValue={item.release_date ? new Date(item.release_date) : null}
render={({ field: { onChange, onBlur, value, ref } }) => (
<ReactDatePicker
onChange={onChange}
onBlur={onBlur}
className="form-control w-full"
dateFormat="MMM dd, yyyy"
selected={value}
/>
)}
/>
<input type="submit" />
</form>
);
}
Here is the screenshot,
Currently, it is showing apr 23, even when I had passed it 04-24. To see the issue, you might have to use some different timezone (where still current date is apr 23).
And, here is the sandbox
There is a different when you use - and /
const date1 = new Date("2022/04/24");
const date2 = new Date("2022-04-24");
document.getElementById("app").innerHTML = `
<h4>${date1}</h4>
<h4>${date2}</h4>
`;
<div id="app">
</div>
https://codesandbox.io/s/date-object-qqjnrs
Luxon implementation: (from the same people who build moment)
https://moment.github.io/luxon/#/?id=luxon
// leave it as a string
const date1 = "2022-04-24";
const date2 = "2022/04/24";
const date1Result = luxon.DateTime.fromFormat(date1, "yyyy-M-dd").toJSDate()
const date2Result = luxon.DateTime.fromFormat(date, "yyyy/M/dd").toJSDate()
console.log({date1Result, date2Result})
(note, in moment js the solution would be similar.)
You can see for yourself by going to the luxon website and writing these lines in the dev tools console.
https://moment.github.io/luxon/#/?id=luxon
Related
I want to show the datepicker year list in Descending order but am unable to do. It shows min date at first and then goes down to the max date.
The code I wrote is written below.
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<DatePicker
views={['year', 'month']}
label="Month"
value={selectedDate}
onChange={(value) => setSelectedDate(value)}
animateYearScrolling
minDate={'01-01-2000'}
maxDate={new Date()}
/>
</MuiPickersUtilsProvider>
You can refer to this implementation on codesandbox to achieve the above mentioned descending order of years in datepicker. If you want more information on this, refer to this feature request thread on github.
import React from "react";
import { MuiPickersUtilsProvider } from "material-ui-pickers";
import MomentUtils from "#date-io/moment";
import { DatePicker } from "material-ui-pickers";
import moment from "moment";
moment.locale();
class LocalizedUtils extends MomentUtils {
getYearRange(start, end) {
const startDate = this.moment(end).startOf("year");
const endDate = this.moment(start).endOf("year");
const years = [];
let current = startDate;
while (current.isAfter(endDate)) {
years.push(current);
current = current.clone().subtract(1, "year");
}
return years;
}
}
class App extends React.Component {
state = { date: new Date() };
handleDateChange = date => {
this.setState({ date });
};
render() {
return (
<MuiPickersUtilsProvider utils={LocalizedUtils}>
<DatePicker
clearable
onChange={this.handleDateChange}
showTabs={false}
variant="outlined"
minDate={new Date("01-01-1900")}
/>
</MuiPickersUtilsProvider>
);
}
}
export default App;
I am stuck with an issue. I am not able to hide and show the react-date-range picker on date selection. Actually, I am using a package for date range selection, Here's the package link - https://www.npmjs.com/package/react-date-range.
This package does not support hiding the date picker once the date range picker is selected. But according to my requirement, the date picker should be visible once the user clicks on the start date or selected date input and should close once the end date is selected.
I have used a state to toggle the view of the date range picker to show it once the user clicks on the input field and closes it on the onChange event. But when ver the user clicks on the date picker it closes since the onChange event is triggered.
Here's my code for a better understanding
import React from 'react'
// import date-range-picker css
import 'react-date-range/dist/styles.css'; // main style file
import 'react-date-range/dist/theme/default.css'; // theme css file
import { DateRangePicker } from 'react-date-range';
export interface IDateRangePickerProps {
range: any[],
onChange: (range: any) => void
}
const CustomDateRangePicker: React.FC<IDateRangePickerProps> = ({ range, onChange }) => {
const TODAY = new Date();
return (
<DateRangePicker
months={2}
minDate={TODAY}
direction="horizontal"
ranges={range}
onChange={onChange}
/>
)
}
export default CustomDateRangePicker;
In the above code, we have created a component to make the react-date-range picker easier to reuse throughout the application.
Here's the implementation of the react-date-range picker
import React, { useEffect, useState } from "react";
import CustomDateRangePicker from "../../components/daterangepicker/DateRangePicker";
import { format } from "date-fns";
const PropertyRoomTypes = () => {
const [showDateRangePicker, setShowDateRangePicker] = useState(false);
const [selectionRange, setSelectionRange] = useState<any[]>([{
startDate: null,
endDate: null,
key: 'selection',
}]);
const onDateRangeChange = (range: any) => {
setSelectionRange([range.selection])
if (selectionRange[0].startDate && selectionRange[0].endDate) {
setShowDateRangePicker(false);
}
}
const formatDate = (date: any) => {
if (date) {
let res = format(new Date(date), "dd MMM yyyy");
return res;
} else {
return;
}
}
return (
<>
<div className="add__room__type__meal__plan__wrapper px-0 mx-0">
<div className="room__rates__edit__date__range__picker" onClick={() => setShowDateRangePicker(!showDateRangePicker)}>
<div className="date__range__picker__icon"><i className="bi bi-calendar"></i></div>
<div className="date__range__label">{`${selectionRange[0].startDate && selectionRange[0].endDate ? formatDate(selectionRange[0].startDate) + " | " + formatDate(selectionRange[0].endDate) : "Select Dates"}`}</div>
{/* <div className="date__range__label">Select Dates</div> */}
</div>
{showDateRangePicker &&
<CustomDateRangePicker
range={selectionRange}
onChange={onDateRangeChange}
/>
}
</div>
</>
);
};
export default PropertyRoomTypes;
Any help would be much appreciated.
When user do first selection, both dates are the same...
So, you should compare it... something like that:
useEffect(() => {
if (selectionRange.startDate !== selectionRange.endDate) {
showDateRangePicker(false);
}
}, [selectionRange]);
I am using Material Ui DateTime picker in a form. After submitting the form, I get the following error:
Invalid Date Format
Image
I am using JSON Server in my react app for saving data.
This is the output Element for the DateTime picker on DOM.
<input aria-invalid="false" readonly="" type="text" class="MuiInputBase-input MuiInput-input" value="March 16th 08:50 a.m.">
This is data on db.json.
{
"text": "study",
"day": "2022-03-16T05:20:00.000Z",
"reminder": true,
"id": 1
}
This is my code for Add date.
import { useState } from "react";
import DateFnsUtils from "#date-io/date-fns";
import { MuiPickersUtilsProvider } from "#material-ui/pickers";
import "date-fns";
import { DateTimePicker } from "#material-ui/pickers";
const AddTask = ({ onAdd }) => {
const [day, setDay] = useState(new Date());
const onSubmit = (e) => {
e.preventDefault();
onAdd({ day });
setDay("");
};
return (
<form className="add-form" onSubmit={onSubmit}>
<div className="form-control">
<label>Day & time</label>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<DateTimePicker
disableToolbar
variant="inline"
value={day}
onChange={(day) => {
setDay(day);
}}
autoOk
/>
</MuiPickersUtilsProvider>
</div>
</form>
);
};
I would appreciate it if you help me. Thanks
It will probably not break if you remove the setDay(""); line from onSubmit. Why do you need it after all?
I have a datepicker and it shows a default value(shows only if the api has a value), when I update it, onchange function doesn't give the selected value. it gives the initial value which is coming from the api. any idea how I can get the updated value to onchange function.
api data
const apidata = my api
setState({
...state,
formData:{
...apidata,
startDate:moment(apidata.startDate).utc()
}
})
form component
<Form
name="update form"
initialValues={state.formData}
autoComplete="off"
form={form}
>
<Form.Item
label="Start Date"
name="startDate"
rules={[{ required: true, message: "Please enter value!!!!!" }]}
>
<DatePicker
value={state.formData?.startDate}
onChange={(date: any)=>updateFields(date)}
/>
</Form.Item>
</Form>
update function
const updateFields = (data:any) => { // here I'm getting the already set api value not the changed value
setState({
...state,
formData : {
startDate:data
}
})
}
The bug is not easy to find if you don't share a minimal reproducible example.
If you use the defaultValue from antd Datepicker API the onChange works as expected.
<DatePicker
defaultValue={moment('2015-01-01', 'YYYY-MM-DD')}
onChange={updateFields}
/>
Here is a small stackblitz which works as expected using antd Datepicker and Form.Item.
E.g.:
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Form, DatePicker } from 'antd';
import moment from 'moment';
const Demo = () => {
const [form] = Form.useForm();
function updateFields(date, dateString) {
console.log(date, dateString);
}
return (
<Form form={form} name="control-hooks">
<Form.Item name="DatePicker">
<DatePicker
defaultValue={moment('2015-01-01', 'YYYY-MM-DD')}
onChange={updateFields}
/>
</Form.Item>
</Form>
);
};
ReactDOM.render(<Demo />, document.getElementById('container'));
I'm beginner in ReactJS and I'm trying to save some dates fields.
By default, the dates are save in format yyyy-MM-dd, but when I able to send the date for the API the format should be in format dd/mm/yyyy.
I already try using .toLocaleDateString('pt-BR', {timeZone: 'UTC'});. But when I did that, return error:
The specified value "19/8/2020" does not conform to the required format, "yyyy-MM-dd".
Here's my code I put in CodeSandBox
And, here where I get the date values:
import React, { useState } from "react";
const NewUser = () => {
const [data, setData] = useState({
birthdate: "",
admission_date: ""
});
const changeField = (field, value) => {
const auxData = { ...data };
auxData[field] = value;
setData(auxData);
};
return (
<div>
<span>Born</span>
<input
id="birthdate"
type="date"
value={data.birthdate}
onChange={(event) => changeField("birthdate", event.target.value)}
/>
<div />
<span>Admission Date</span>
<input
id="admission_date"
type="date"
value={data.admission_date}
onChange={(event) => changeField("admission_date", event.target.value)}
/>
</div>
);
};
export default NewUser;
Don't import the entire momentjs library just for this simple task.
// yyyy-MM-dd
const input = "2020-08-19"
const [year, month, day] = input.split('-')
// dd/mm/yyyy
console.log(`${day}/${month}/${year}`)
Also, check out You-Dont-Need-Momentjs for some lighter alternatives, and even some native methods for common use cases of handling dates.
Also, you probably want to wait until you're ready to send the data to the server before applying the transformation (instead of trying to do this inside changeField). Example: