Skip to content

Commit e4c828a

Browse files
committed
feat: add controlled state
1 parent d2727ec commit e4c828a

7 files changed

Lines changed: 54 additions & 25 deletions

File tree

packages/react-use-calendar-component/src/app/components/Examples/Multiple.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
import { useEffect } from 'react';
1+
import { useState } from 'react';
22

33
import useCalendarComponent from '../../../lib';
44
import Calendar from '../Calendar';
55
import SelectedDates from '../SelectedDates';
66

77
export function Multiple() {
8-
const calendarControl = useCalendarComponent({ selectType: 'multiple' });
9-
const { selectedDates, value } = calendarControl;
10-
// const { year, month, dayOfMonth } = selectedDate;
11-
12-
useEffect(() => {
13-
console.log('value:', value);
14-
}, [value]);
8+
const [value, setValue] = useState([new Date()]);
9+
console.log(value);
10+
const calendarControl = useCalendarComponent({
11+
selectType: 'multiple',
12+
value,
13+
onChange: setValue,
14+
});
15+
const { selectedDates } = calendarControl;
1516

1617
return (
1718
<div>

packages/react-use-calendar-component/src/app/components/Examples/Single.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import { useState } from 'react';
2+
13
import useCalendarComponent from '../../../lib';
24
import Calendar from '../Calendar';
35
import SelectedDates from '../SelectedDates';
46

57
export function Single() {
6-
const calendarControl = useCalendarComponent();
8+
const [value, setValue] = useState(new Date());
9+
const calendarControl = useCalendarComponent({ value, onChange: setValue });
710
const { selectedDates } = calendarControl;
811

912
return (

packages/react-use-calendar-component/src/lib/hooks/useCalendarComponent.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ import type {
66
DateCellInfo,
77
SelectDateOptions,
88
SelectType,
9+
Value,
910
} from '../types';
10-
import { getDateInfoByIndex } from '../utils';
11+
import { getDateInfoByIndex, isSameDate, noop } from '../utils';
1112
import useDisplayedDate from './useDisplayedDate';
1213

1314
export default function useCalendarComponent<S extends SelectType = 'single'>({
1415
initialDisplayedDate = new Date(),
1516
selectType,
16-
defaultValue,
17+
value,
18+
onChange = noop,
1719
}: UseCalendarOptions<S> = {}) {
1820
const {
1921
displayedYear,
@@ -23,8 +25,23 @@ export default function useCalendarComponent<S extends SelectType = 'single'>({
2325
changeDisplayedYear,
2426
changeDisplayedMonth,
2527
} = useDisplayedDate(initialDisplayedDate);
26-
const [selectedDates, setSelectedDates] = useState<Date[]>([]);
27-
const [value, setValue] = useState(defaultValue);
28+
const [internalValue, setInternalValue] = useState(value);
29+
const selectedDates = (() => {
30+
if (selectType === 'multiple') {
31+
if (value) return value as Date[];
32+
if (internalValue) return internalValue as Date[];
33+
}
34+
35+
if (value) return [value] as Date[];
36+
if (internalValue) return [internalValue] as Date[];
37+
38+
return [];
39+
})();
40+
41+
const handleValueChange = (value: Value<S>) => {
42+
onChange(value);
43+
setInternalValue(value);
44+
};
2845

2946
const getDateCellInfo = (
3047
year: number,
@@ -46,30 +63,26 @@ export default function useCalendarComponent<S extends SelectType = 'single'>({
4663
const selectedDate = new Date(dateYear, dateMonth, dayOfMonth);
4764
if (selectType === 'multiple') {
4865
const newDates = selectedDates.filter(
49-
date => date.toString() !== selectedDate.toString()
66+
date => !isSameDate(date, selectedDate)
5067
);
5168
if (newDates.length === selectedDates.length)
5269
newDates.push(selectedDate);
5370
newDates.sort((a, b) => a.getTime() - b.getTime());
54-
setSelectedDates(newDates);
55-
setValue(newDates as any);
71+
handleValueChange(newDates as any);
5672

5773
return;
5874
}
5975

60-
setSelectedDates([selectedDate]);
61-
setValue(selectedDate as any);
76+
handleValueChange(selectedDate as any);
6277
};
6378

6479
return {
6580
key: `${dateYear}-${dateMonth}-${dayOfMonth}`,
6681
year: dateYear,
6782
month: dateMonth,
6883
dayOfMonth: dayOfMonth,
69-
isSelected: !!selectedDates.find(
70-
date =>
71-
date.toString() ===
72-
new Date(dateYear, dateMonth, dayOfMonth).toString()
84+
isSelected: !!selectedDates.find(date =>
85+
isSameDate(date, new Date(dateYear, dateMonth, dayOfMonth))
7386
),
7487
selectThisDate,
7588
...info,
@@ -92,7 +105,6 @@ export default function useCalendarComponent<S extends SelectType = 'single'>({
92105
selectedDates,
93106
displayedYear,
94107
displayedMonth,
95-
value,
96108
changeDisplayedYear,
97109
changeDisplayedMonth,
98110
getDateCellInfos,

packages/react-use-calendar-component/src/lib/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// useCalendarComponent
22
export type SelectType = 'single' | 'multiple';
33

4-
export type DefaultValue<S extends SelectType> = S extends 'single'
4+
export type Value<S extends SelectType> = S extends 'single'
55
? Date
66
: S extends 'multiple'
77
? Date[]
@@ -10,7 +10,8 @@ export type DefaultValue<S extends SelectType> = S extends 'single'
1010
export type UseCalendarOptions<S extends SelectType = 'single'> = {
1111
initialDisplayedDate?: Date;
1212
selectType?: S;
13-
defaultValue?: DefaultValue<S>;
13+
value?: Value<S>;
14+
onChange?: (value: Value<S>) => void;
1415
};
1516

1617
export interface DateInfo {

packages/react-use-calendar-component/src/lib/utils/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ export * from './getNumberOfDays';
22
export * from './isToday';
33
export * from './locale';
44
export * from './getDateInfo';
5+
export * from './noop';
6+
export * from './isSameDate';
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export function isSameDate(a: Date, b: Date) {
2+
if (a.getFullYear() !== b.getFullYear()) return false;
3+
if (a.getMonth() !== b.getMonth()) return false;
4+
if (a.getDate() !== b.getDate()) return false;
5+
return true;
6+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2+
export function noop(...args: any[]) {
3+
return;
4+
}

0 commit comments

Comments
 (0)