import { createContext, ReactElement, ReactNode, useContext, useEffect, useState } from 'react'; import { AppState, AppStateStatus } from 'react-native'; interface Props { children: ReactNode; } const AppStateContext = createContext(undefined); /** * @name AppStateProvider * @description * 토스 React Native 화면의 `AppState`를 관리하는 Provider예요. 이 Provider는 앱의 상태(활성, 백그라운드 등)를 관리하고, 이를 구독하는 자식 컴포넌트로 전달해요. * @link https://reactnative.dev/docs/appstate * @param {Props} children - `AppStateProvider`로 감쌀 자식 컴포넌트에요. 이 컴포넌트는`AppState`의 변화를 감지하고 반응할 수 있어요. * @returns {ReactElement} - `AppStateProvider` 로 감싼 React Provider 컴포넌트예요. * @example * ```tsx * export function App() { * return ( * * * * ); * } * ``` */ export function AppStateProvider({ children }: Props): ReactElement { const [appState, setAppState] = useState(AppState.currentState); const handleAppStateChange = (status: AppStateStatus) => { setAppState(status); }; useEffect(() => { const subscription = AppState.addEventListener('change', handleAppStateChange); return () => { subscription.remove(); }; }, []); return {children}; } /** * @category Hooks * @name useIsAppForeground * @description * React Native 앱이 포그라운드(foreground) 상태인지 여부를 반환해요. * * @see https://reactnative.dev/docs/0.72/appstate#app-states * @returns {boolean} - 앱이 포그라운드 상태인지 여부를 반환해요. * @throws {Error} 관리 중인 AppState의 상태가 `null`일 때 에러를 발생시켜요. * @example * ```typescript * const isForeground = useIsAppForeground(); * ``` */ export const useIsAppForeground = (): boolean => { const appState = useContext(AppStateContext); if (appState == null) { throw new Error('useIsAppForeground must be used within a AppStateProvider'); } /** * iOS 에서는 'inactive' 상태도 포그라운드(foreground)로 간주해요. * 'inactive' 는 iOS 에서만 존재하는 상태로, 예를 들어 제어센터나 알림창이 떠 있는 상태예요. * @see https://reactnative.dev/docs/0.72/appstate#app-states */ return appState === 'active' || appState === 'inactive'; };