+
{children}
);
diff --git a/frontend/src/components/DatePicker/DatePicker.stories.tsx b/frontend/src/components/DatePicker/DatePicker.stories.tsx
index d7c81b14..5855e433 100644
--- a/frontend/src/components/DatePicker/DatePicker.stories.tsx
+++ b/frontend/src/components/DatePicker/DatePicker.stories.tsx
@@ -5,7 +5,7 @@ import { useHighlightRange } from '@/hooks/useDatePicker/useHighlightRange';
import { useMonthNavigation } from '@/hooks/useDatePicker/useMonthNavigation';
import { useSharedCalendar } from '@/hooks/useSharedCalendar';
-import { SharedCalendarContext } from '../Calendar/context/SharedCalendarContext';
+import { SharedCalendarProvider } from '../Calendar/context/SharedCalendarContext';
import Input from '../Input';
import DatePicker from '.';
import { injectedContainerStyle } from './datePicker.stories.css';
@@ -93,13 +93,13 @@ export const SyncWithSharedContext = () => {
const monthNavigation = useMonthNavigation();
return (
-
+
{/* */}
-
+
);
};
diff --git a/frontend/src/components/DatePicker/Header/index.tsx b/frontend/src/components/DatePicker/Header/index.tsx
index da825463..147f1401 100644
--- a/frontend/src/components/DatePicker/Header/index.tsx
+++ b/frontend/src/components/DatePicker/Header/index.tsx
@@ -1,15 +1,14 @@
import { Flex } from '@/components/Flex';
import { ChevronLeft, ChevronRight } from '@/components/Icon';
import { Text } from '@/components/Text';
-import { useSafeContext } from '@/hooks/useSafeContext';
import { vars } from '@/theme/index.css';
import { getDateParts } from '@/utils/date';
-import { DatePickerContext } from '../context/DatePickerContext';
+import { useDatePickerContext } from '../context/DatePickerContext';
import { chevronWrapper, headerStyle } from './index.css';
const Header = () => {
- const { baseDate, gotoNextMonth, gotoPrevMonth } = useSafeContext(DatePickerContext);
+ const { baseDate, gotoNextMonth, gotoPrevMonth } = useDatePickerContext();
const { year: currentYear, month: currentMonth } = getDateParts(baseDate);
return (
diff --git a/frontend/src/components/DatePicker/Table/Cell/DateCell.tsx b/frontend/src/components/DatePicker/Table/Cell/DateCell.tsx
index d7196041..0de4f3b6 100644
--- a/frontend/src/components/DatePicker/Table/Cell/DateCell.tsx
+++ b/frontend/src/components/DatePicker/Table/Cell/DateCell.tsx
@@ -1,11 +1,10 @@
import { assignInlineVars } from '@vanilla-extract/dynamic';
-import { useSafeContext } from '@/hooks/useSafeContext';
import { vars } from '@/theme/index.css';
import { isSameDate, isSaturday, isSunday } from '@/utils/date';
import type { DatePickerType } from '../..';
-import { DatePickerContext } from '../../context/DatePickerContext';
+import { useDatePickerContext } from '../../context/DatePickerContext';
import type { HighlightState } from '../Highlight';
import { cellThemeVars } from '../index.css';
import CellWrapper from './CellWrapper';
@@ -33,7 +32,7 @@ export const DateCell = ({
baseDate,
highlightState,
}: DateCellProps) => {
- const { calendarType, onDateCellClick } = useSafeContext(DatePickerContext);
+ const { calendarType, onDateCellClick } = useDatePickerContext();
const todayCellStyle = getTodayCellStyle(calendarType);
const selectedCellStyle = getSelectedCellStyle(calendarType);
const inlineCellStyles = assignInlineVars(cellThemeVars, {
diff --git a/frontend/src/components/DatePicker/Table/Row.tsx b/frontend/src/components/DatePicker/Table/Row.tsx
index 81f7de43..79230f2d 100644
--- a/frontend/src/components/DatePicker/Table/Row.tsx
+++ b/frontend/src/components/DatePicker/Table/Row.tsx
@@ -1,7 +1,6 @@
-import { useSafeContext } from '@/hooks/useSafeContext';
import { isSameDate } from '@/utils/date';
-import { DatePickerContext } from '../context/DatePickerContext';
+import { useDatePickerContext } from '../context/DatePickerContext';
import { DateCell } from './Cell';
import type { HighlightRange, HighlightState } from './Highlight';
import HighlightBox from './Highlight/HighlightBox';
@@ -13,7 +12,7 @@ interface RowProps {
}
const Row = ({ weekDates }: RowProps) => {
- const { baseDate, highlightRange, isDateSelected } = useSafeContext(DatePickerContext);
+ const { baseDate, highlightRange, isDateSelected } = useDatePickerContext();
return (
diff --git a/frontend/src/components/DatePicker/Table/TableBody.tsx b/frontend/src/components/DatePicker/Table/TableBody.tsx
index 3af2c941..3f52fd28 100644
--- a/frontend/src/components/DatePicker/Table/TableBody.tsx
+++ b/frontend/src/components/DatePicker/Table/TableBody.tsx
@@ -1,13 +1,12 @@
import { Flex } from '@/components/Flex';
-import { useSafeContext } from '@/hooks/useSafeContext';
import { generateMonthCalendar } from '@/utils/date/calendar/calendarGeneration';
-import { DatePickerContext } from '../context/DatePickerContext';
+import { useDatePickerContext } from '../context/DatePickerContext';
import Row from './Row';
const TableBody = () => {
- const { baseDate } = useSafeContext(DatePickerContext);
+ const { baseDate } = useDatePickerContext();
const calendarDates = generateMonthCalendar(baseDate ?? new Date());
return (
boolean;
}
-export const DatePickerContext = createContext(null);
+export const {
+ StateProvider: DatePickerProvider,
+ useContextState: useDatePickerContext,
+} = createStateContext();
diff --git a/frontend/src/components/DatePicker/context/DatePickerRangeProvider.tsx b/frontend/src/components/DatePicker/context/DatePickerRangeProvider.tsx
index e3eb76eb..265248dd 100644
--- a/frontend/src/components/DatePicker/context/DatePickerRangeProvider.tsx
+++ b/frontend/src/components/DatePicker/context/DatePickerRangeProvider.tsx
@@ -4,7 +4,7 @@ import { useDatePickerRange } from '@/hooks/useDatePicker/useDatePickerRange';
import { isSameDate } from '@/utils/date';
import type { DatePickerRangeProps } from '../DatePickerRange';
-import { DatePickerContext } from './DatePickerContext';
+import { DatePickerProvider } from './DatePickerContext';
interface DatePickerRangeProviderProps extends PropsWithChildren, DatePickerRangeProps {}
@@ -26,8 +26,8 @@ const DatePickerRangeProvider = ({
}, [highlightRange]);
return (
-
{children}
-
+
);
};
diff --git a/frontend/src/components/DatePicker/context/DatePickerSelectProvider.tsx b/frontend/src/components/DatePicker/context/DatePickerSelectProvider.tsx
index 8c291ea5..dce638b4 100644
--- a/frontend/src/components/DatePicker/context/DatePickerSelectProvider.tsx
+++ b/frontend/src/components/DatePicker/context/DatePickerSelectProvider.tsx
@@ -4,7 +4,7 @@ import { useDatePickerSelect } from '@/hooks/useDatePicker/useDatePickerSelect';
import { isSameDate } from '@/utils/date';
import type { DatePickerSelectProps } from '../DatePickerSelect';
-import { DatePickerContext } from './DatePickerContext';
+import { DatePickerProvider } from './DatePickerContext';
interface DatePickerRangeProviderProps extends PropsWithChildren, DatePickerSelectProps {}
@@ -17,8 +17,8 @@ const DatePickerSelectProvider = ({
props.selectedDate ? isSameDate(date, props.selectedDate) : false;
return (
-
{children}
-
+
);
};
diff --git a/frontend/src/components/Dropdown/DropdownContext.ts b/frontend/src/components/Dropdown/DropdownContext.ts
index 97c4c0e1..3718a3cd 100644
--- a/frontend/src/components/Dropdown/DropdownContext.ts
+++ b/frontend/src/components/Dropdown/DropdownContext.ts
@@ -1,4 +1,4 @@
-import { createContext } from 'react';
+import { createStateContext } from '@/utils/context';
interface DropdownContextProps {
controlId: string;
@@ -15,4 +15,7 @@ interface DropdownContextProps {
* @param onChange - Dropdown 컴포넌트의 값 변경 함수.
* @param setIsOpen - Dropdown 컴포넌트의 오픈 상태 변경 함수.
*/
-export const DropdownContext = createContext(null);
\ No newline at end of file
+export const {
+ StateProvider: DropdownProvider,
+ useContextState: useDropdownContext,
+} = createStateContext();
\ No newline at end of file
diff --git a/frontend/src/components/Dropdown/DropdownItem.tsx b/frontend/src/components/Dropdown/DropdownItem.tsx
index ac705de2..99123c36 100644
--- a/frontend/src/components/Dropdown/DropdownItem.tsx
+++ b/frontend/src/components/Dropdown/DropdownItem.tsx
@@ -1,11 +1,10 @@
import type { CSSProperties, PropsWithChildren } from 'react';
import { useId } from 'react';
-import { useSafeContext } from '@/hooks/useSafeContext';
import clsx from '@/utils/clsx';
import { Text } from '../Text';
-import { DropdownContext } from './DropdownContext';
+import { useDropdownContext } from './DropdownContext';
import { dropdownStyle } from './dropdownItem.css';
interface DropdownItemProps extends PropsWithChildren {
@@ -16,7 +15,7 @@ interface DropdownItemProps extends PropsWithChildren {
}
export const DropdownItem = ({ value, style, onClick, className, children }: DropdownItemProps) => {
- const { controlId, selectedValue, onChange, setIsOpen } = useSafeContext(DropdownContext);
+ const { controlId, selectedValue, onChange, setIsOpen } = useDropdownContext();
const defaultId = `${controlId}-item-${useId()}`;
const handleClick = () => {
diff --git a/frontend/src/components/Dropdown/index.tsx b/frontend/src/components/Dropdown/index.tsx
index d203fce2..b6192362 100644
--- a/frontend/src/components/Dropdown/index.tsx
+++ b/frontend/src/components/Dropdown/index.tsx
@@ -4,7 +4,7 @@ import { useId, useState } from 'react';
import { useClickOutside } from '@/hooks/useClickOutside';
import { DropdownContents } from './DropdownContents';
-import { DropdownContext } from './DropdownContext';
+import { DropdownProvider } from './DropdownContext';
import { DropdownItem } from './DropdownItem';
import { dropdownContainerStyle, dropdownTriggerStyle } from './index.css';
@@ -28,8 +28,8 @@ export const Dropdown = ({
const [isOpen, setIsOpen] = useState(false);
const ref = useClickOutside(() => setIsOpen(false));
return (
-
{isOpen && children}
-
+
);
};
diff --git a/frontend/src/components/Group/GroupContext.ts b/frontend/src/components/Group/GroupContext.ts
index 539c694b..1c4f0c01 100644
--- a/frontend/src/components/Group/GroupContext.ts
+++ b/frontend/src/components/Group/GroupContext.ts
@@ -1,15 +1,4 @@
-import { createContext } from 'react';
-
-import { useSafeContext } from '@/hooks/useSafeContext';
-
-interface GroupContextProps {
- controlId: string;
- checkedList: Set
;
- onToggleCheck: (id: number) => void;
- onToggleAllCheck: () => void;
- reset: () => void;
- isAllChecked: boolean;
-}
+import { createStateContext } from '@/utils/context';
/**
* @description Group 컴포넌트의 Context.
@@ -21,6 +10,17 @@ interface GroupContextProps {
* @param [reset] - Group 컴포넌트의 체크박스를 초기화하는 함수.
* @param [isAllChecked] - Group 컴포넌트의 전체 체크박스가 체크되었는지 여부.
*/
-export const GroupContext = createContext(null);
+interface GroupContextProps {
+ controlId: string;
+ checkedList: Set;
+ onToggleCheck: (id: number) => void;
+ onToggleAllCheck: () => void;
+ reset: () => void;
+ isAllChecked: boolean;
+}
-export const useGroupContext = () => useSafeContext(GroupContext);
\ No newline at end of file
+export const {
+ StateProvider: GroupProvider,
+ useContextState: useGroupContext,
+ useUnsafeContextState: useUnsafeGroupContext,
+} = createStateContext();
\ No newline at end of file
diff --git a/frontend/src/components/Group/index.tsx b/frontend/src/components/Group/index.tsx
index a7120303..f997dcec 100644
--- a/frontend/src/components/Group/index.tsx
+++ b/frontend/src/components/Group/index.tsx
@@ -3,7 +3,7 @@ import { useId } from 'react';
import type { GroupStateReturn } from '@/hooks/useGroup';
-import { GroupContext } from './GroupContext';
+import { GroupProvider } from './GroupContext';
export interface GroupProps extends PropsWithChildren {
groupInfos: GroupStateReturn;
@@ -23,8 +23,8 @@ export const Group = ({
const { checkedList, isAllChecked, handleToggleCheck, handleToggleAllCheck, reset } = groupInfos;
return (
-
{children}
-
+
);
};
\ No newline at end of file
diff --git a/frontend/src/components/Input/Core/InputField.tsx b/frontend/src/components/Input/Core/InputField.tsx
index 1b25ba34..53dfe368 100644
--- a/frontend/src/components/Input/Core/InputField.tsx
+++ b/frontend/src/components/Input/Core/InputField.tsx
@@ -2,12 +2,11 @@ import type { InputHTMLAttributes } from 'react';
import { useRef } from 'react';
import { ChevronDown } from '@/components/Icon';
-import { useSafeContext } from '@/hooks/useSafeContext';
import { vars } from '@/theme/index.css';
import clsx from '@/utils/clsx';
import { interactableBorderStyle } from '../index.css';
-import { InputContext } from '../InputContext';
+import { useInputContext } from '../InputContext';
import { inputFieldContainerStyle, inputFieldStyle, selectIconStyle } from './inputField.css';
interface InputFieldProps extends Omit, 'onClick'> {
@@ -15,7 +14,7 @@ interface InputFieldProps extends Omit, 'o
}
const InputField = ({ placeholder, onClick, ...inputProps }: InputFieldProps) => {
- const { isValid, type, borderPlacement } = useSafeContext(InputContext);
+ const { isValid, type, borderPlacement } = useInputContext();
const inputRef = useRef(null);
const handleContainerClick = () => {
diff --git a/frontend/src/components/Input/InputContext.ts b/frontend/src/components/Input/InputContext.ts
index 4bd6ae65..89b1bf2d 100644
--- a/frontend/src/components/Input/InputContext.ts
+++ b/frontend/src/components/Input/InputContext.ts
@@ -1,4 +1,4 @@
-import { createContext } from 'react';
+import { createStateContext } from '@/utils/context';
import type { CommonInputProps } from '.';
@@ -14,4 +14,7 @@ interface InputContextProps {
* @Param {isValid} boolean - Input 컴포넌트가 Error 상태인지 여부.
* @Param {type} InputProps['type'] - Input 컴포넌트의 타입.
*/
-export const InputContext = createContext(null);
+export const {
+ StateProvider: InputProvider,
+ useContextState: useInputContext,
+} = createStateContext();
\ No newline at end of file
diff --git a/frontend/src/components/Input/MultiInput.tsx b/frontend/src/components/Input/MultiInput.tsx
index c586fa2b..5e00f5f1 100644
--- a/frontend/src/components/Input/MultiInput.tsx
+++ b/frontend/src/components/Input/MultiInput.tsx
@@ -15,7 +15,7 @@ import {
interactableBorderStyle,
separatorStyle,
} from './index.css';
-import { InputContext } from './InputContext';
+import { InputProvider } from './InputContext';
export interface MultiInputProps extends CommonInputProps, PropsWithChildren {
separator?: string | JSX.Element;
@@ -42,7 +42,7 @@ export const MultiInput = ({
childElements.length > 1 ? intersperseElement(childElements, separatorElement) : childElements;
return (
-
+
-
+
);
};
diff --git a/frontend/src/components/Input/SingleInput.tsx b/frontend/src/components/Input/SingleInput.tsx
index 4d3a5ce1..e693a15d 100644
--- a/frontend/src/components/Input/SingleInput.tsx
+++ b/frontend/src/components/Input/SingleInput.tsx
@@ -7,7 +7,7 @@ import HelperText from './Core/HelperText';
import InputField from './Core/InputField';
import Label from './Core/Label';
import { containerStyle, inputFieldsContainerStyle, interactableBorderStyle } from './index.css';
-import { InputContext } from './InputContext';
+import { InputProvider } from './InputContext';
export interface SingleInputProps extends CommonInputProps {
inputProps?: Omit, 'placeholder' | 'onClick' | 'readOnly'>;
@@ -25,7 +25,7 @@ export const SingleInput = ({
inputProps = {},
className,
}: SingleInputProps) => (
-
+
{label &&
{label} }
@@ -41,6 +41,6 @@ export const SingleInput = ({
isValid={isValid}
/>
-
+
);
export default SingleInput;
\ No newline at end of file
diff --git a/frontend/src/components/Notification/NotificationContext.ts b/frontend/src/components/Notification/NotificationContext.ts
deleted file mode 100644
index 54a89da2..00000000
--- a/frontend/src/components/Notification/NotificationContext.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { createContext } from 'react';
-
-import type { NotificationWithOptionalId } from '@/hooks/useNotification';
-
-interface NotificationContextProps {
- addNoti: (notification: NotificationWithOptionalId) => void;
-}
-
-export const NotificationContext = createContext
(null);
\ No newline at end of file
diff --git a/frontend/src/components/SegmentControl/Content.tsx b/frontend/src/components/SegmentControl/Content.tsx
index dbd32da2..7c09d21c 100644
--- a/frontend/src/components/SegmentControl/Content.tsx
+++ b/frontend/src/components/SegmentControl/Content.tsx
@@ -1,10 +1,9 @@
import type { PropsWithChildren } from 'react';
-import { useSafeContext } from '@/hooks/useSafeContext';
import clsx from '@/utils/clsx';
import { contentContainerStyle } from './index.css';
-import { SegmentControlContext } from './SegmentControlContext';
+import { useSegmentControlContext } from './SegmentControlContext';
interface ContentProps extends PropsWithChildren {
value: string;
@@ -12,7 +11,7 @@ interface ContentProps extends PropsWithChildren {
}
const Content = ({ value, className, children }: ContentProps) => {
- const { selectedValue } = useSafeContext(SegmentControlContext);
+ const { selectedValue } = useSegmentControlContext();
if (selectedValue !== value) return null;
return (
diff --git a/frontend/src/components/SegmentControl/ControlButton.tsx b/frontend/src/components/SegmentControl/ControlButton.tsx
index 1e7a675f..8a4b036d 100644
--- a/frontend/src/components/SegmentControl/ControlButton.tsx
+++ b/frontend/src/components/SegmentControl/ControlButton.tsx
@@ -1,8 +1,6 @@
-import { useSafeContext } from '@/hooks/useSafeContext';
-
import Button from '../Button';
import type { SegmentControlProps, SegmentOption } from '.';
-import { SegmentControlContext } from './SegmentControlContext';
+import { useSegmentControlContext } from './SegmentControlContext';
interface ControlButtonProps {
segmentOption: SegmentOption;
@@ -15,7 +13,7 @@ const ControlButton = ({
segmentControlStyle,
onButtonHover,
}: ControlButtonProps ) => {
- const { selectedValue, handleSelect } = useSafeContext(SegmentControlContext);
+ const { selectedValue, handleSelect } = useSegmentControlContext();
const { label, value } = segmentOption;
return (
void;
}
-export const SegmentControlContext = createContext(null);
\ No newline at end of file
+export const {
+ StateProvider: SegmentControlProvider,
+ useContextState: useSegmentControlContext,
+} = createStateContext();
\ No newline at end of file
diff --git a/frontend/src/components/SegmentControl/index.tsx b/frontend/src/components/SegmentControl/index.tsx
index 0cb4e6f0..d6ca8759 100644
--- a/frontend/src/components/SegmentControl/index.tsx
+++ b/frontend/src/components/SegmentControl/index.tsx
@@ -5,7 +5,7 @@ import { Flex } from '../Flex';
import Content from './Content';
import ControlButton from './ControlButton';
import { controlButtonContainerStyle } from './index.css';
-import { SegmentControlContext } from './SegmentControlContext';
+import { SegmentControlProvider } from './SegmentControlContext';
export interface SegmentOption {
label: string;
@@ -38,7 +38,7 @@ const SegmentControl = ({
};
return (
-
+
{children}
-
+
);
};
diff --git a/frontend/src/components/Tab/TabContent.tsx b/frontend/src/components/Tab/TabContent.tsx
index ced3a3fe..7ce819c8 100644
--- a/frontend/src/components/Tab/TabContent.tsx
+++ b/frontend/src/components/Tab/TabContent.tsx
@@ -1,11 +1,10 @@
import type { PropsWithChildren } from 'react';
import { useId } from 'react';
-import { useSafeContext } from '@/hooks/useSafeContext';
import clsx from '@/utils/clsx';
import { tabContentStyle } from './index.css';
-import { TabContext } from './TabContext';
+import { useTabContext } from './TabContext';
interface TabContentProps extends PropsWithChildren {
value: string;
@@ -13,7 +12,7 @@ interface TabContentProps extends PropsWithChildren {
}
export const TabContent = ({ value, className, children }: TabContentProps) => {
- const { controlId, selectedValue, onChange } = useSafeContext(TabContext);
+ const { controlId, selectedValue, onChange } = useTabContext();
const defaultId = `${controlId}-item-${useId()}`;
const handleClick = () => {
diff --git a/frontend/src/components/Tab/TabContext.ts b/frontend/src/components/Tab/TabContext.ts
index 2d30c0c1..c076e13f 100644
--- a/frontend/src/components/Tab/TabContext.ts
+++ b/frontend/src/components/Tab/TabContext.ts
@@ -1,4 +1,4 @@
-import { createContext } from 'react';
+import { createStateContext } from '@/utils/context';
export interface TabContextProps {
controlId: string;
@@ -13,4 +13,7 @@ export interface TabContextProps {
* @param selectedValue - Tab 컴포넌트의 선택된 값.
* @param onChange - Tab 컴포넌트의 값 변경 함수.
*/
-export const TabContext = createContext | null>(null);
\ No newline at end of file
+export const {
+ StateProvider: TabProvider,
+ useContextState: useTabContext,
+} = createStateContext, TabContextProps, object>();
\ No newline at end of file
diff --git a/frontend/src/components/Tab/TabItem.tsx b/frontend/src/components/Tab/TabItem.tsx
index 889d943c..774709da 100644
--- a/frontend/src/components/Tab/TabItem.tsx
+++ b/frontend/src/components/Tab/TabItem.tsx
@@ -1,18 +1,16 @@
import type { PropsWithChildren } from 'react';
import { useId } from 'react';
-import { useSafeContext } from '@/hooks/useSafeContext';
-
import { Text } from '../Text';
import { tabItemStyle } from './index.css';
-import { TabContext } from './TabContext';
+import { useTabContext } from './TabContext';
interface TabItemProps extends PropsWithChildren {
value: string;
}
export const TabItem = ({ value, children }: TabItemProps) => {
- const { controlId, selectedValue, onChange } = useSafeContext(TabContext);
+ const { controlId, selectedValue, onChange } = useTabContext();
const defaultId = `${controlId}-item-${useId()}`;
const handleClick = () => {
diff --git a/frontend/src/components/Tab/index.tsx b/frontend/src/components/Tab/index.tsx
index 1ae4b6ac..a1653a68 100644
--- a/frontend/src/components/Tab/index.tsx
+++ b/frontend/src/components/Tab/index.tsx
@@ -5,7 +5,7 @@ import clsx from '@/utils/clsx';
import { tabContainerStyle } from './index.css';
import { TabContent } from './TabContent';
-import { TabContext } from './TabContext';
+import { TabProvider } from './TabContext';
import { TabItem } from './TabItem';
import { TabItemList } from './TabItemList';
@@ -24,8 +24,8 @@ export const Tab = ({
const defaultId = `Tab-${useId()}`;
return (
- void,
@@ -34,7 +34,7 @@ export const Tab = ({
{children}
-
+
);
};
diff --git a/frontend/src/features/my-calendar/ui/CalendarCard/CardContents.tsx b/frontend/src/features/my-calendar/ui/CalendarCard/CardContents.tsx
index de5e1fcf..e6591385 100644
--- a/frontend/src/features/my-calendar/ui/CalendarCard/CardContents.tsx
+++ b/frontend/src/features/my-calendar/ui/CalendarCard/CardContents.tsx
@@ -12,7 +12,7 @@ const CalendarCardChip = ({ status, size }: Pick
+
{adjustmentStatusMap[status].label}
);
diff --git a/frontend/src/features/my-calendar/ui/OngoingDiscussion/OngoingCardList.tsx b/frontend/src/features/my-calendar/ui/OngoingDiscussion/OngoingCardList.tsx
index efc76b14..734e2ce3 100644
--- a/frontend/src/features/my-calendar/ui/OngoingDiscussion/OngoingCardList.tsx
+++ b/frontend/src/features/my-calendar/ui/OngoingDiscussion/OngoingCardList.tsx
@@ -41,12 +41,12 @@ export const OngoingCardList = () => {
const handleClickSelect = (discussion: OngoingSchedule | null) => {
if (!discussion) {
- setSelectedId(null);
+ setSelectedId?.(null);
reset();
return;
}
const { start, end, sh, sm, eh, em } = formatDateTimeRange(discussion);
- setSelectedId(discussion.discussionId);
+ setSelectedId?.(discussion.discussionId);
handleSelectDateRange(
setTimeOnly(start, { hour: sh, minute: sm }),
setTimeOnly(end, { hour: eh, minute: em }),
diff --git a/frontend/src/features/shared-schedule/ui/OngoingSchedules/RecommendedSchedules.tsx b/frontend/src/features/shared-schedule/ui/OngoingSchedules/RecommendedSchedules.tsx
index a7c133a1..d8877a4c 100644
--- a/frontend/src/features/shared-schedule/ui/OngoingSchedules/RecommendedSchedules.tsx
+++ b/frontend/src/features/shared-schedule/ui/OngoingSchedules/RecommendedSchedules.tsx
@@ -101,7 +101,7 @@ const AvailableChip = ({ adjustCount }: { adjustCount: number }) => (
color={adjustCount > 0 ? 'red' : 'blue'}
radius='max'
size='md'
- style='weak'
+ variant='weak'
>
{adjustCount > 0 ? `조율 필요 ${adjustCount}` : '모두 가능'}
diff --git a/frontend/src/features/shared-schedule/ui/UpcomingSchedules/ScheduleCard.tsx b/frontend/src/features/shared-schedule/ui/UpcomingSchedules/ScheduleCard.tsx
index c330574b..b7423613 100644
--- a/frontend/src/features/shared-schedule/ui/UpcomingSchedules/ScheduleCard.tsx
+++ b/frontend/src/features/shared-schedule/ui/UpcomingSchedules/ScheduleCard.tsx
@@ -66,7 +66,7 @@ const DdayChip = ({ endDateTime, latest }: {
color={latest ? 'black' : 'coolGray'}
radius='max'
size='md'
- style={latest ? 'filled' : 'weak'}
+ variant={latest ? 'filled' : 'weak'}
>
{formatDateToDdayString(endDateTime)}
diff --git a/frontend/src/features/shared-schedule/ui/UpcomingSchedules/UpcomingScheduleListItem.tsx b/frontend/src/features/shared-schedule/ui/UpcomingSchedules/UpcomingScheduleListItem.tsx
index ed65b661..91f79fc5 100644
--- a/frontend/src/features/shared-schedule/ui/UpcomingSchedules/UpcomingScheduleListItem.tsx
+++ b/frontend/src/features/shared-schedule/ui/UpcomingSchedules/UpcomingScheduleListItem.tsx
@@ -71,7 +71,7 @@ const Content = ({
{formatDateToDdayString(startDate)}
diff --git a/frontend/src/features/timeline-schedule/ui/TimelineContext.ts b/frontend/src/features/timeline-schedule/ui/TimelineContext.ts
index a10e1395..1b49f134 100644
--- a/frontend/src/features/timeline-schedule/ui/TimelineContext.ts
+++ b/frontend/src/features/timeline-schedule/ui/TimelineContext.ts
@@ -1,12 +1,11 @@
-import { createContext } from 'react';
-
-import { useSafeContext } from '@/hooks/useSafeContext';
+import { createStateContext } from '@/utils/context';
interface TimelineContextProps {
isConfirmedSchedule: boolean;
handleGoBack: () => void;
}
-export const TimelineContext = createContext(null);
-
-export const useTimelineContext = () => useSafeContext(TimelineContext);
\ No newline at end of file
+export const {
+ StateProvider: TimelineProvider,
+ useContextState: useTimelineContext,
+} = createStateContext();
\ No newline at end of file
diff --git a/frontend/src/features/timeline-schedule/ui/index.tsx b/frontend/src/features/timeline-schedule/ui/index.tsx
index c9053fb5..fd2b220f 100644
--- a/frontend/src/features/timeline-schedule/ui/index.tsx
+++ b/frontend/src/features/timeline-schedule/ui/index.tsx
@@ -16,7 +16,7 @@ import {
topBarStyle,
} from './index.css';
import TimelineContent from './TimelineContent';
-import { TimelineContext, useTimelineContext } from './TimelineContext';
+import { TimelineProvider, useTimelineContext } from './TimelineContext';
import { splitParticipantsBySelection } from './timelineHelper';
// TODO: context로 옮길 수 있는 prop들 찾아서 옮기기
@@ -47,7 +47,7 @@ const TimelineScheduleModal = ({
);
return (
-
+
-
+
);
};
diff --git a/frontend/src/hooks/useCalendar.ts b/frontend/src/hooks/useCalendar.ts
index 4844a276..7e6efcbb 100644
--- a/frontend/src/hooks/useCalendar.ts
+++ b/frontend/src/hooks/useCalendar.ts
@@ -1,9 +1,10 @@
import { useState } from 'react';
-import type { CalendarSharedInfo } from '@/components/Calendar/context/SharedCalendarContext';
import { isObjectEmpty } from '@/utils/common';
import { formatDateToWeekDates } from '@/utils/date';
+import type { CalendarSharedInfo } from './useSharedCalendar';
+
export interface CalendarInfo {
selected: Date;
dates: Date[];
diff --git a/frontend/src/hooks/useCheckbox.ts b/frontend/src/hooks/useCheckbox.ts
index 6d18fe8f..6e56f3eb 100644
--- a/frontend/src/hooks/useCheckbox.ts
+++ b/frontend/src/hooks/useCheckbox.ts
@@ -1,8 +1,8 @@
import type { SetStateAction } from 'react';
-import { useContext, useState } from 'react';
+import { useState } from 'react';
-import { GroupContext } from '../components/Group/GroupContext';
+import { useUnsafeGroupContext } from '@/components/Group/GroupContext';
interface CheckedStateProps {
defaultChecked?: boolean;
@@ -24,7 +24,7 @@ export const useCheckbox = ({
onToggleCheck,
type,
}: CheckedStateProps): UseCheckboxReturn => {
- const group = useContext(GroupContext);
+ const group = useUnsafeGroupContext();
const [checked, setChecked] = useState(defaultChecked || false);
const handleClickCheck = () => {
diff --git a/frontend/src/hooks/useNotification.ts b/frontend/src/hooks/useNotification.ts
deleted file mode 100644
index aa7f9daa..00000000
--- a/frontend/src/hooks/useNotification.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-
-import { useCallback, useReducer } from 'react';
-
-import type { NotificationProps } from '../components/Notification';
-
-export type NotificationWithOptionalId = NotificationProps & {
- id?: number;
-};
-
-export type NotificationWithId = NotificationProps & {
- id: number;
-};
-
-type NotificationState = {
- notifications: NotificationWithId[];
-};
-
-export type NotificationAction = { type: 'ADD_NOTIFICATION'; notification: NotificationWithId }
-| { type: 'REMOVE_NOTIFICATION'; id: number };
-
-export const notificationReducer = (state: NotificationState, action: NotificationAction) => {
- switch (action.type) {
- case 'ADD_NOTIFICATION': {
- return { notifications: [...state.notifications, action.notification] };
- }
- case 'REMOVE_NOTIFICATION': {
- const newNotifications = state.notifications
- .filter((notification) => notification.id !== action.id);
- return { notifications: newNotifications };
- }
- default:
- return state;
- }
-};
-
-export const useNotification = () => {
- const [state, dispatch] = useReducer(notificationReducer, { notifications: [] });
-
- const addNoti = (notification: NotificationWithOptionalId) => {
- // TODO: 유니크한 id 생성하기. (따닥 이슈)
- const defaultId = notification.id || new Date().getTime();
-
- dispatch({ type: 'ADD_NOTIFICATION', notification: { ...notification, id: defaultId } });
- setTimeout(() => {
- dispatch({ type: 'REMOVE_NOTIFICATION', id: defaultId });
- }, 3000);
- };
-
- const memoizedAddNoti = useCallback(addNoti, []);
-
- return { state, addNoti: memoizedAddNoti };
-};
\ No newline at end of file
diff --git a/frontend/src/hooks/useSharedCalendar.ts b/frontend/src/hooks/useSharedCalendar.ts
index c0bb3e57..10cf5188 100644
--- a/frontend/src/hooks/useSharedCalendar.ts
+++ b/frontend/src/hooks/useSharedCalendar.ts
@@ -1,10 +1,18 @@
import { useState } from 'react';
-import type { CalendarSharedInfo } from '@/components/Calendar/context/SharedCalendarContext';
-
import { formatDateToWeekDates } from '../utils/date';
import { useMonthNavigation } from './useDatePicker/useMonthNavigation';
+export interface CalendarSharedInfo {
+ selectedDate: Date;
+ selectedWeek: Date[];
+ handleSelectDate: (date: Date) => void;
+ today: Date;
+ baseDate: Date;
+ gotoPrevMonth: () => void;
+ gotoNextMonth: () => void;
+}
+
export const useSharedCalendar = (): CalendarSharedInfo => {
const [selected, setSelected] = useState(new Date());
const { baseDate, setBaseDate, gotoPrevMonth, gotoNextMonth } = useMonthNavigation();
diff --git a/frontend/src/pages/MyCalendarPage/DiscussionContext.ts b/frontend/src/pages/MyCalendarPage/DiscussionContext.ts
index fb6086a6..e2fe43db 100644
--- a/frontend/src/pages/MyCalendarPage/DiscussionContext.ts
+++ b/frontend/src/pages/MyCalendarPage/DiscussionContext.ts
@@ -1,13 +1,18 @@
import type { Dispatch, SetStateAction } from 'react';
-import { createContext } from 'react';
-import { useSafeContext } from '@/hooks/useSafeContext';
-import type { DateRangeReturn } from '@/hooks/useSelectDateRange';
+import { type DateRangeReturn, useSelectDateRange } from '@/hooks/useSelectDateRange';
+import { createStateContext } from '@/utils/context';
-interface DiscussionContextProps extends DateRangeReturn {
+interface DiscussionContextProps {
selectedId: number | null;
setSelectedId: Dispatch>;
}
-export const DiscussionContext = createContext(null);
-export const useDiscussionContext = () => useSafeContext(DiscussionContext);
\ No newline at end of file
+export const {
+ StateProvider: DiscussionProvider,
+ useContextState: useDiscussionContext,
+} = createStateContext<
+ DiscussionContextProps & DateRangeReturn,
+ DateRangeReturn,
+ DiscussionContextProps
+>(useSelectDateRange);
\ No newline at end of file
diff --git a/frontend/src/pages/MyCalendarPage/TableContext.ts b/frontend/src/pages/MyCalendarPage/TableContext.ts
index 1042e19b..ddd5f742 100644
--- a/frontend/src/pages/MyCalendarPage/TableContext.ts
+++ b/frontend/src/pages/MyCalendarPage/TableContext.ts
@@ -1,7 +1,7 @@
-import { createContext } from 'react';
+import { useScrollToTime } from '@/hooks/useScrollToTime';
+import { createStateContext } from '@/utils/context';
-import { useSafeContext } from '@/hooks/useSafeContext';
-import type { ScrollTableProps } from '@/hooks/useScrollToTime';
-
-export const TableContext = createContext(null);
-export const useTableContext = () => useSafeContext(TableContext);
\ No newline at end of file
+export const {
+ StateProvider: TableProvider,
+ useContextState: useTableContext,
+} = createStateContext(useScrollToTime);
\ No newline at end of file
diff --git a/frontend/src/pages/MyCalendarPage/index.tsx b/frontend/src/pages/MyCalendarPage/index.tsx
index 05919852..d658da70 100644
--- a/frontend/src/pages/MyCalendarPage/index.tsx
+++ b/frontend/src/pages/MyCalendarPage/index.tsx
@@ -1,25 +1,22 @@
import { useState } from 'react';
-import { SharedCalendarContext } from '@/components/Calendar/context/SharedCalendarContext';
+import { SharedCalendarProvider } from '@/components/Calendar/context/SharedCalendarContext';
import { Divider } from '@/components/Divider';
import { Flex } from '@/components/Flex';
import { Text } from '@/components/Text';
import { MyCalendar } from '@/features/my-calendar/ui/MyCalendar';
import SideBar from '@/features/my-calendar/ui/SideBar';
-import { useScrollToTime } from '@/hooks/useScrollToTime';
import { useSelectDateRange } from '@/hooks/useSelectDateRange';
-import { useSharedCalendar } from '@/hooks/useSharedCalendar';
-import { DiscussionContext } from './DiscussionContext';
+import { DiscussionProvider } from './DiscussionContext';
import {
containerStyle,
contentStyle,
titleContainerStyle,
} from './index.css';
-import { TableContext } from './TableContext';
+import { TableProvider } from './TableContext';
const MyCalendarPage = () => {
- const calendar = useSharedCalendar();
const [selectedId, setSelectedId] = useState(null);
return (
@@ -29,19 +26,19 @@ const MyCalendarPage = () => {
-
-
+
-
+
-
-
-
+
+
+
);
diff --git a/frontend/src/pages/UpcomingScheduleDetailPage/index.tsx b/frontend/src/pages/UpcomingScheduleDetailPage/index.tsx
index dd33788a..da004497 100644
--- a/frontend/src/pages/UpcomingScheduleDetailPage/index.tsx
+++ b/frontend/src/pages/UpcomingScheduleDetailPage/index.tsx
@@ -46,7 +46,7 @@ const TopBarContent = ({ scheduleInfo, end }: { scheduleInfo: ScheduleInfo; end:
color='coolGray'
radius='max'
size='md'
- style='weak'
+ variant='weak'
>
{formatDateToDdayString(end)}
diff --git a/frontend/src/types/defaultProps.ts b/frontend/src/types/defaultProps.ts
new file mode 100644
index 00000000..1a46452a
--- /dev/null
+++ b/frontend/src/types/defaultProps.ts
@@ -0,0 +1,6 @@
+import type { CSSProperties, PropsWithChildren } from 'react';
+
+export interface DefaultProps extends PropsWithChildren {
+ className?: string;
+ style?: CSSProperties;
+}
\ No newline at end of file
diff --git a/frontend/src/utils/context/createStateContext.tsx b/frontend/src/utils/context/createStateContext.tsx
new file mode 100644
index 00000000..afb49e40
--- /dev/null
+++ b/frontend/src/utils/context/createStateContext.tsx
@@ -0,0 +1,33 @@
+import type { PropsWithChildren } from 'react';
+import { createContext, useContext } from 'react';
+
+import { useSafeContext } from '@/hooks/useSafeContext';
+
+interface StateProviderProps