I'm creating a DatePicker and using useState hook to manage it's visibility. On div click I've added the event listener which changes value, but it didn't work as I expected. It works only the first time, so initial value changes to true, but on second and third clicks this value stays to true and DatePicker stays visible on click.
This is DatePicker
import React, { useState } from 'react';
import OutsideClickHandler from 'react-outside-click-handler';
import { renderInfo, getWeeksForMonth } from './utils';
import {
renderMonthAndYear,
handleBack,
handleNext,
weekdays,
} from '../../utils';
const DatePicker = ({
isOpen,
setIsOpen,
selected,
setSelected,
dayClick,
dayClass,
}) => {
const startDay = new Date().setHours(0, 0, 0, 0);
const [current, setCurrent] = useState(new Date(startDay));
const weeks = getWeeksForMonth(current.getMonth(), current.getFullYear());
function handleClick(date) {
if (date > startDay) {
setSelected(date);
setCurrent(date);
setIsOpen(false);
if (dayClick) {
dayClick(date);
}
}
}
return (
<div className="DatePicker-container">
<div
tabIndex="0"
role="button"
className="DatePicker-info"
onKeyPress={e => {
if (e.which === 13) {
setIsOpen(!isOpen);
}
}}
onClick={e => {
setIsOpen(!isOpen);
}}
>
{renderInfo(selected)}
</div>
{isOpen && (
<OutsideClickHandler onOutsideClick={() => setIsOpen(false)}>
<div className="DatePicker">
<div className="DatePicker__header">
<span
role="button"
onClick={() => handleBack(current, setCurrent)}
className="triangle triangle--left"
/>
<span className="DatePicker__title">
{renderMonthAndYear(current)}
</span>
<span
role="button"
onClick={() => handleNext(current, setCurrent)}
className="triangle triangle--right"
/>
</div>
<div className="DatePicker__weekdays">
{weekdays.map(weekday => (
<div
key={weekday}
className="DatePicker__weekday"
>
{weekday}
</div>
))}
</div>
{weeks.map((week, index) => (
<div
role="row"
key={index}
className="DatePicker__week"
>
{week.map((date, index) =>
date ? (
<div
role="cell"
key={index}
onClick={() => handleClick(date)}
className={dayClass(date)}
>
{date.getDate()}
</div>
) : (
<div
key={index}
className="DatePicker__day--empty"
/>
),
)}
</div>
))}
</div>
</OutsideClickHandler>
)}
</div>
);
};
export default DatePicker;
DateRangePicker which uses two.
import React, { useState } from 'react';
import DatePicker from './DatePicker';
import DatePickerContext from './DatePickerContext';
import './DatePicker.scss';
const DateRangePicker = () => {
const startDay = new Date().setHours(0, 0, 0, 0);
const [isOpen, setIsOpen] = useState(false);
const [isSecondOpen, setIsSecondOpen] = useState(false);
const [selected, setSelected] = useState(new Date(startDay));
const [secondSelected, setSecondSelected] = useState(new Date(startDay));
function dayClass(date) {
if (
selected.getTime() === date.getTime() ||
(date >= selected && date <= secondSelected)
) {
return 'DatePicker__day DatePicker__day--selected';
}
if (date < startDay || date < selected) {
return 'DatePicker__day DatePicker__day--disabled';
}
return 'DatePicker__day';
}
function dayClick(date) {
setSecondSelected(date);
setIsSecondOpen(true);
}
return (
<DatePickerContext.Provider>
<div className="DatePicker-wrapper">
<DatePicker
key={1}
isOpen={isOpen}
setIsOpen={setIsOpen}
selected={selected}
setSelected={setSelected}
dayClick={dayClick}
dayClass={dayClass}
/>
<DatePicker
key={2}
isOpen={isSecondOpen}
setIsOpen={setIsSecondOpen}
selected={secondSelected}
setSelected={setSecondSelected}
dayClass={dayClass}
/>
</div>
</DatePickerContext.Provider>
);
};
export default DateRangePicker;