Identify selected date range in react-date-range - reactjs

I am using react-date-range plugin to select a date range.
import { DateRangePicker} from 'react-date-range';
import 'react-date-range/dist/styles.css';
import 'react-date-range/dist/theme/default.css';
Following function is used to handle the date range when a range is selected
function handleSelect() {
}
I have added the DateRangePicker like this
const selectionRange = {
startDate: new Date(),
endDate: new Date(),
key: 'selection',
}
<div>
<DateRangePicker
ranges={[selectionRange]}
onChange={handleSelect}/>
</div>
I want to make some operations on the selected date range in side the handleChange function. But I cannot find how to identify which date range is selected and the respective start and end dates.
In documentation onChange callback is described as
But I cannot understand how to get these startDate and endDate parameters.
Can someone help me to get this values.
Documentation: https://openbase.io/js/react-date-range/documentation

According to the documentation the onChange callback receives the ranges as an argument:
import { DateRangePicker } from 'react-date-range';
class MyComponent extends Component {
handleSelect(ranges){
console.log(ranges);
// {
// selection: {
// startDate: [native Date Object],
// endDate: [native Date Object],
// }
// }
}
render(){
const selectionRange = {
startDate: new Date(),
endDate: new Date(),
key: 'selection',
}
return (
<DateRangePicker
ranges={[selectionRange]}
onChange={this.handleSelect}
/>
)
}
}
It should be an object that has a key selection which is itself an object that contains the startDate and endDate.

My solution is:
const onChange = (item) => {
if (item.selection.endDate !== item.selection.startDate) {
console.log(item);
setIsPopoverOpen(false);
}
setRange([item.selection]);
}

Related

React state not updating props (using next.js)

Trying to update the state of a react-date-range object (next.js) in a component with useState / setState. Not sure what I'm doing wrong, but I keep getting an error that dateRange.startDate is undefined.
import {useState, React} from 'react'
import { DefinedRange } from 'react-date-range'
import PropTypes from 'prop-types'
export const DataCard = ({...props}) => {
let [dateRange, setDateRange] = useState([{
startDate: props.dateRange.startDate,
endDate: props.dateRange.endDate,
key: 'selection'
}])
const updateDateRange = (dateRange) => {
props.dateRange = {startDate: dateRange.startDate, endDate: dateRange.endDate}
setDateRange([props.dateRange.startDate, props.dateRange.endDate])
}
return (
<div>
<div>
<button>
<DefinedRange onChange={item=> {updateDateRange([item.selection])}} ranges={dateRange}/>
</button>
</div>
</div>
)}
DataCard.propTypes = {
header: PropTypes.string,
dateRangeComponent: PropTypes.element,
dateRange: PropTypes.object
}
DataCard.defaultProps = {
header: "Graph Name",
dateRange: {startDate: new Date(), endDate: new Date()}
}
Your dispatch code is a bit problematic.
const updateDateRange = (dateRange) => {
console.log(dataRange)
props.dateRange = {startDate: dateRange.startDate, endDate: dateRange.endDate}
setDateRange([props.dateRange.startDate, props.dateRange.endDate])
}
I suspect two things therefore i suggest to add a console.log.
Possibility 1
Maybe your input isn't an array, instead it's a e from event handler. So first need to confirm that by printing it onto screen.
Possibility 2
When you change something, you'd like to take changes from your input, not prop. So you need to think of why you are using props in the dispatch. Props are coming from parent, not children. Use local variable instead.
Bonus
Normally we don't render stuff inside a <button> element. It might be irrelevant to your problem, but might complicate your other parts of work. Use <div> instead.
Your initial status is an array of 1 object but when you setDateRange, you provide an array of two objects
Your init data:
[{
startDate: props.dateRange.startDate,
endDate: props.dateRange.endDate,
key: 'selection'
}] // an array of a object
setDateRange([props.dateRange.startDate, props.dateRange.endDate]) // setDateRange([a, b]), array of two objects
It should be:
setDateRange((prevState) => ({ startDate: props.startDate, endDate: props.endDate, key: prevState.key }));

React Hooks selecting data to a date picker

I have a MUI date picker in my React app that I want to use with serverside data.
I'm returning the correct data in my console log that I pass in my useState hook const [availableDate, setAvailableDate] = useState({}); and now want to pass the selected date into the picker:
returned JSON
const data = [
{
date: '05/05/21',
timeSlots: [
{
end: '11:00',
start: '12:00'
}
]
},
{
date: '05/05/24',
timeSlots: [
{
end: '13:00',
start: '14:00'
}
]
}
];
Date Picker
const [availableDate, setAvailableDate] = useState({});
const [filteredData, setFilteredData] = useState(availableDate);
//set current date as default
var curr = new Date();
function setDate(dat) {
let datt = {
date: {// ... returend date},
start: '11:40',
end: '13:00',
};
service.stepDate.setCvData(datt);
}
curr.setDate(curr.getDate());
var date = curr.toISOString().substr(0, 10);
Date Picker
I tried mapping the array data in my date picker but this just returns multiple pickers.
{availableDates.map((index) => (
<div className="calendarWrapper">
<form noValidate>
<TextField
key={index.id}
minDate={today}
id="date"
type="date"
onChange={setDate}
defaultValue={date}
/>
</form>
</div>
))}
How do I extract the selected date ex: date: "2021/05/24" from the json and pass it into my setDate() function?
First of all, onChange interface is the following
onChange(e) {
// e.target.value
}
so you won't be able to get your date from e directly.
Also date is an object, which can't be {} initially, null could be one option, or new Date().

Set timezone React-Datepicker

I'm using the react-datepicker to let user select a date. However, right now it uses local time (PDT), but I want to hardcode it to use a specific timezone (PST).
I tried using utcOffset prop but it doesn't seem to be doing anything. Does anyone know how to accomplish this?
For my part I set the defaultTimezone before rendering the React-dates plugin.
React-dates will just use the default timezone.
moment.tz.setDefault('America/Los_Angeles');
This works for me:
import React, { ComponentProps } from "react"
import DatePicker from "react-datepicker"
import moment from "moment"
interface Props {
timezone: string
}
const DatePickerWithTimezone = ({
selected,
onChange,
timezone,
...props
}: Props & ComponentProps<typeof DatePicker>) => (
<DatePicker
selected={selected ? setLocalZone(selected, timezone) : null}
onChange={(v, e) => {
onChange(v ? setOtherZone(v, timezone) : null, e)
}}
{...props}
/>
)
const setLocalZone = (date: Date, timezone: string) => {
const dateWithoutZone = moment
.tz(date, timezone)
.format("YYYY-MM-DDTHH:mm:ss.SSS")
const localZone = moment(dateWithoutZone).format("Z")
const dateWithLocalZone = [dateWithoutZone, localZone].join("")
return new Date(dateWithLocalZone)
}
const setOtherZone = (date: Date, timezone: string) => {
const dateWithoutZone = moment(date).format("YYYY-MM-DDTHH:mm:ss.SSS")
const otherZone = moment.tz(date, timezone).format("Z")
const dateWithOtherZone = [dateWithoutZone, otherZone].join("")
return new Date(dateWithOtherZone)
}
export default DatePickerWithTimezone
since datepicker doesn't use moment.js anymore i tried to implement a hacky solution for this issue, assuming the initial value is a string for instance:
export const formatUTC = (dateInt, addOffset = false) => {
let date = (!dateInt || dateInt.length < 1) ? new Date : new Date(dateInt);
if (typeof dateInt === "string") {
return date;
} else {
const offset = addOffset ? date.getTimezoneOffset() : -(date.getTimezoneOffset());
const offsetDate = new Date();
offsetDate.setTime(date.getTime() + offset * 60000)
return offsetDate;
}
}
inside date i call the formatter like this:
selected={formatUTC(this.props.input.value,true)}
onChange={date => formatUTC(date)}
I've been thru this, If you decided that you want to just ignore your local offset then you can hardcode the zone.
Observation just to give a complete answer: PST will always be -08:00, but if you want for example pacific time, right now is -07:00, in this case, you may want to install 'moment.timezone' then import moment from 'moment-timezone' and just get the current offset with moment.tz('US/Pacific').format('Z')
The code in typescript (I can change it to Javascript if you want):
interface ICalendarInputProps {
handleChange: (newDate: moment.Moment) => void;
}
const CalendarInput = ({ handleChange }: ICalendarInputProps) => {
const onChange = (date: Date) => {
handleChange(moment(`${moment(date).format('YYYY-MM-DDThh:mm:ss')}-08:00`));
// This is to get the offset from a timezone: handleChange(moment(`${moment(date).format('YYYY-MM-DDThh:mm:ss')}${moment.tz('US/Pacific').format('Z')}`));
};
return (<DatePicker onChange={onChange} />);
};
export default CalendarInput;
This component outputs Date objects set to midnight local-time at the start of the chosen day. This is a problem. If there is a way of configuring this behaviour, I haven't found it.
The only way to stay sane when dealing with dates is to make sure that your dates are always midnight UTC at the start of the date in question. To get this behaviour from react-datepicker, the only thing I've found is to subtract the timezone offset from the output...
interface IProps {
value: any
setValue: (value: Date) => void
}
const DayPicker: FC<IProps> = ({ value, setValue, placeholderText = "", minDate = new Date() }) => {
function correctToUtcThenSet(val: Date) {
setValue(new Date(val.getTime() - val.getTimezoneOffset() * 60000))
}
return <DatePicker
onChange={correctToUtcThenSet}
selected={value}
/>
}
Other answers didn't work as I'd hoped, and sometimes the dates were off by 1 day because of time zone differences.
This is what I needed:
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { getEndOfDayUtc, treatLocalDateAsUtcMidnight, treatUtcMidnightAsLocalDate } from '../../../shared/helpers/datetime';
type DatePickerUtcProps = {
selected: Date | string;
onChange: any;
isEndOfDay: boolean;
};
function getSelectedAsLocal(selected: Date | string): Date {
const selectedDate = typeof selected === 'string' ? new Date(selected) : selected;
return treatUtcMidnightAsLocalDate(selectedDate);
}
export function DatePickerUtc({ selected, onChange, isEndOfDay, ...datePickerProps }: DatePickerUtcProps): JSX.Element {
function onChangeAsUtc(local: Date) {
const utc = treatLocalDateAsUtcMidnight(local);
const adjusted = isEndOfDay ? getEndOfDayUtc(utc) : utc;
console.log('onChangeAsUtc', { local, utc, adjusted, isEndOfDay });
onChange(adjusted);
}
return <DatePicker onChange={onChangeAsUtc} selected={getSelectedAsLocal(selected)} {...datePickerProps} />;
}
export function treatLocalDateAsUtcMidnight(localDate: Date): Date {
const moment = dayjs(localDate).tz('UTC', true); // https://day.js.org/docs/en/plugin/timezone
const utcMidnight = getStartOfDayUtc(moment.toDate());
console.log({ localDate, utcMidnight });
return utcMidnight;
}
export function treatUtcMidnightAsLocalDate(utcMidnight: Date): Date {
const sliceOfJustTheDatePart = utcMidnight.toISOString().slice(0, 10);
const localDate = dayjs(sliceOfJustTheDatePart).toDate();
console.log({ localDate, sliceOfJustTheDatePart, utcMidnight });
return localDate;
}
From: <DatePickerUtc selected={startDate} onChange={(utcDate: Date) => setStartDate(utcDate)} {...datePickerProps} />
To: <DatePickerUtc selected={endDate} onChange={(utcDate: Date) => setEndDate(utcDate)} {...datePickerPropsEndOfDay} />
I also didn't have luck with utcOffset. You could use moment-timezone in your project instead of moment and convert it yourself:
import moment from "moment-timezone";
onDateChange = date => {
console.log("as is:", date.format("YYYY-MM-DD HH:mm:ss"));
console.log("PST:", moment(date).tz("America/Los_Angeles").format("YYYY-MM-DD HH:mm:ss"));
};
Sandbox: https://codesandbox.io/s/y2vwj9mwpz
Since you're using moment.js, you can try using moment.utc() and subtract hours to pst timezone.
moment.utc().startOf('day').subtract(8, 'hours')

React Datepicker( can't get value of input)

I am new in react. I need use react-datepicker
I want to get value of input, when I change date.
If i click on 20th October 2017, i want put 20th October 2017 in my variable.
But the main problem that I should work with component, not with input.
Before I just took value from state. Like this.state.value. But right now it is object(Moment) in state. And this object doesn't have value field.
There is my code:
export default class DatePicker extends Component {
constructor (props) {
super(props);
// this.props.date should looks like "29 November 2017 00:00"
// second argument for moment() it is format of date, because RFC 2822 date time format
this.state = {
date: moment(this.props.value, 'LLL')
};
}
handleChange = (date) => {
// const valueOfInput = this.state.date <--- I want string with date here
console.log('this.state.date',this.state.date);
this.setState({date: date});
};
render() {
return <Form.Field>
<Label>
<Picker
selected={this.state.date}
onChange={this.handleChange}
dateFormat="LLL"
locale={this.props.language}
/>
</Label>
</Form.Field>
Just use this:
handleChange = date => {
const valueOfInput = date.format();
///...
};
Because this datepicker returns a moment.js object!
For more information, look into the moment.js docs here.
Try this
<DatePicker
onChange={(value, e) => this.handleChange(value, e)}
selected={this.state.inputValue} otherProps={here}
/>
// you can access the value field in handleChange by e.target.value
handleChange(value, e) {
console.log(value); // this will be a moment date object
console.log(e.target.value); // this will be a string value in datepicker input field
}
This solved for me by using the following:
handleDateChange = date => {
let selectedDateFromCalender = date.toUTCString();
this.setState({
actualStartDate: selectedDateFromCalender,
});}
<DatePicker
selected={this.state.startDate}
onChange={this.handleDateChange}/>
You can use the following methods as well, choose according to your requirement:
toISOString: "2020-10-05T09:10:38.000Z"
toJSON: "2020-10-06T09:09:16.000Z"
toUTCString: "Thu, 08 Oct 2020 09:11:24 GMT"
If you want to get the new value (once the user clicks on a new date from DatePicker) pass the event to the method.
class MyComponent extends React.Component {
constructor(props) {
this.state = {inputValue: moment(),} // this will set the initial date to "today",
// you could also put another prop.state value there
this.handleChange = this.handleChange.bind(this);
}
}
handleChange(value) {
console.log(value); // this will be a moment date object
// now you can put this value into state
this.setState({inputValue: value});
}
render(){
...
<DatePicker
onChange={(event) => this.handleChange(event)}
selected={this.state.inputValue} otherProps={here} />
...
}
};
The new version of react-datepicker library stopped using a moment.js object, so here is my solution if you want to get a formatted string representation of the date.
First import
import format from "date-fns/format";
Then
<DatePicker
onChange={(value)=>this.handleChange(format(value, "yyyy/MM/dd", {
awareOfUnicodeTokens: true }))}
dateFormat="yyyy/MM/dd"
selected={this.state.inputValue} otherProps={here} />
...
You can use the getTime() helper function on your date object to get the millisecond timestamp for that specific date, which is a JavaScript number data type. Useful for saving data in the backend of your application. For example Flask Peewee ORM requires a timestamp to be saved for the DateTimeField.
const [startDate, setStartDate] = useState(new Date())
<DatePicker
onSelect( date => {
setStartDate(getTime(date))
}
/>
source: https://date-fns.org/v2.0.0-alpha.7/docs/getTime
Combine it with an effect to set the default state value to a timestamp on page load:
useEffect(() => {
setStartDate(getTime(startDate))
}, [])
Otherwise for your UI, you can use the format() helper function to get the string value of the given object, with any given format:
<h1>{format(startDate, "MMMM d, yyyy h:mm aa")}</h1>
source: https://date-fns.org/v2.0.0-alpha.7/docs/format
I have same problem, and I solved it by using the below solution. Please try it:
<p>{this.state.date.toLocaleDateString()}</p>
<input id="tdate" type="date" name="todate" onchange="getToDate(event);">
function getToDate(e){
const tdate = e.target.value;
//alert(tdate);
//console.log(tdate);
//return tdate;
};
here i am trying to access "tdate" variable outside the function.

Using react-datepicker in react-data-grid compoent

I am using react-data-grid component. It provides a grid structure with edit and lot more options. When we click on each cell, we are able to edit the content of the cell. In my project, I have a situation like when the date column is focused I want to bind a UI where the user can able to select the date.for that, I have used react-datepicker component. I am able to give react-datepicker component as a formatter in the date column option. I can able to change the date in the react datepicker component, but that is not updating the cell value (when you click on the console data button you can able to see the changes have been updated or not).so guys help me how I can update the cell value when a different date is selected in the react-datepicker component. It happening automatically when the value is changed in other cells.
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDataGrid from 'react-data-grid';
import DatePicker from 'react-datepicker';
import moment from 'moment';
//helper to generate a random date
function randomDate(start, end) {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())).toLocaleDateString();
}
//helper to create a fixed number of rows
function createRows(numberOfRows){
var _rows = [];
for (var i = 1; i < numberOfRows; i++) {
_rows.push({
id: i,
task: 'Task ' + i,
startDate: randomDate(new Date(2015, 3, 1), new Date())
});
}
return _rows;
}
//function to retrieve a row for a given index
var rowGetter = function(i){
return _rows[i];
};
//renders react datepicker component
var ExampleDate = React.createClass({
displayName: 'Example',
getInitialState: function() {
return {
startDate:moment(this.props.value,"MM-DD-YYYY")
};
},
consoleDate:function(){
console.log(this.state.startDate);
},
handleChange: function(date) {
this.setState({
startDate: date
});
},
render: function() {
return (
<div>
<DatePicker selected={this.state.startDate} onChange={this.handleChange} />
</div>
);
}
});
//Columns definition
var columns = [
{
key: 'id',
name: 'ID',
width: 80
},
{
key: 'task',
name: 'Title',
editable : true,
width:100
},
{
key: 'startDate',
name: 'Start Date',
editable : true,
formatter:<ExampleDate />,
width:100
}
]
var Example = React.createClass({
getInitialState : function(){
return {rows : createRows(5)}
},
rowGetter : function(rowIdx){
return this.state.rows[rowIdx]
},
handleRowUpdated : function(e){
//merge updated row with current row and rerender by setting state
var rows = this.state.rows;
Object.assign(rows[e.rowIdx], e.updated);
this.setState({rows:rows});
},
output:function(){
console.log(this.state.rows);
},
render:function(){
return(
<div>
<ReactDataGrid
enableCellSelect={true}
columns={columns}
rowGetter={this.rowGetter}
rowsCount={this.state.rows.length}
minHeight={200}
onRowUpdated={this.handleRowUpdated} />
<button onClick={this.output} > Console data </button>
</div>
)
}
});
ReactDOM.render(<Example />, document.getElementById('container'));
I encounter some issues when I tried to reproduce. Anyway, after some changes I works fine:
- I removed the random date to avoid "Invalid Date"
- I fixed the formatter like this
formatter: ({value}) => <ExampleDate value={value} />
All works fine, but I always get the warning, because of the key props of your columns :(

Resources