🔥 React Native
React Query는 React Native와 함께 사용할 수 있도록 설계되었습니다. 단, 개발 도구는 현재 React DOM에서만 지원됩니다.
React Native 환경에서 개발 도구를 사용하고 싶다면 다음과 같은 제3자 플러그인을 활용할 수 있습니다:
- Expo 플러그인: https://github.com/expo/dev-plugins/tree/main/packages/react-query
- Flipper 플러그인: https://github.com/bgaleotti/react-query-native-devtools
- Reactotron 플러그인: https://github.com/hsndmr/reactotron-react-query
React Query 팀은 내장 개발 도구를 다양한 플랫폼에서 사용할 수 있도록 만들고 싶어 합니다. 이 작업에 도움을 주고 싶다면 연락 주시기 바랍니다!
온라인 상태 관리
React Query는 웹 브라우저에서 자동으로 재연결 시 다시 가져오기 기능을 지원합니다. React Native에서 이 기능을 사용하려면 React Query의 onlineManager를 다음과 같이 활용해야 합니다:
import NetInfo from '@react-native-community/netinfo' import { onlineManager } from '@tanstack/react-query' onlineManager.setEventListener((setOnline) => { return NetInfo.addEventListener((state) => { setOnline(!!state.isConnected) }) })
typescript
앱 포커스 시 다시 가져오기
React Native에서는 창 이벤트 리스너 대신 AppState 모듈을 통해 포커스 정보를 제공합니다. AppState의 "change" 이벤트를 사용하여 앱 상태가 "active"로 변경될 때 업데이트를 트리거할 수 있습니다:
import { useEffect } from 'react' import { AppState, Platform } from 'react-native' import type { AppStateStatus } from 'react-native' import { focusManager } from '@tanstack/react-query' function onAppStateChange(status: AppStateStatus) { if (Platform.OS !== 'web') { focusManager.setFocused(status === 'active') } } useEffect(() => { const subscription = AppState.addEventListener('change', onAppStateChange) return () => subscription.remove() }, [])
typescript
화면 포커스 시 새로 고침
React Native 화면이 다시 포커스를 받을 때 쿼리를 다시 가져오고 싶을 수 있습니다. 다음 사용자 정의 훅은 화면이 다시 포커스를 받을 때 제공된 refetch 함수를 호출합니다:
import React from 'react' import { useFocusEffect } from '@react-navigation/native' export function useRefreshOnFocus<T>(refetch: () => Promise<T>) { const firstTimeRef = React.useRef(true) useFocusEffect( React.useCallback(() => { if (firstTimeRef.current) { firstTimeRef.current = false return } refetch() }, [refetch]), ) }
typescript
이 코드에서는 useFocusEffect가 마운트 시에도 콜백을 호출하기 때문에 처음에는 refetch를 건너뜁니다.
포커스를 잃은 화면에서 재렌더링 비활성화
성능 문제 등의 이유로 React Native 화면이 포커스를 잃었을 때 재렌더링을 중지하고 싶을 수 있습니다. 이를 위해 @react-navigation/native의 useFocusEffect와 쿼리의 notifyOnChangeProps 옵션을 함께 사용할 수 있습니다.
다음 사용자 정의 훅은 화면이 포커스를 잃었을 때 빈 배열을 반환하는 notifyOnChangeProps 옵션을 제공합니다. 이렇게 하면 해당 상황에서 재렌더링이 중지됩니다. 화면이 다시 포커스를 받으면 정상적인 동작으로 돌아갑니다:
import React from 'react' import { NotifyOnChangeProps } from '@tanstack/query-core' import { useFocusEffect } from '@react-navigation/native' export function useFocusNotifyOnChangeProps( notifyOnChangeProps?: NotifyOnChangeProps, ) { const focusedRef = React.useRef(true) useFocusEffect( React.useCallback(() => { focusedRef.current = true return () => { focusedRef.current = false } }, []), ) return () => { if (!focusedRef.current) { return [] } if (typeof notifyOnChangeProps === 'function') { return notifyOnChangeProps() } return notifyOnChangeProps } }
typescript
이 코드에서는 useFocusEffect를 사용하여 콜백이 조건으로 사용할 참조 값을 변경합니다.
인자는 반환된 콜백이 항상 동일한 참조를 유지하도록 참조로 감싸집니다.
사용 예제:
function MyComponent() { const notifyOnChangeProps = useFocusNotifyOnChangeProps() const { dataUpdatedAt } = useQuery({ queryKey: ['myKey'], queryFn: async () => { const response = await fetch( '<https://api.github.com/repos/tannerlinsley/react-query>', ) return response.json() }, notifyOnChangeProps, }) return <Text>DataUpdatedAt: {dataUpdatedAt}</Text> }
typescript
포커스를 잃은 화면에서 쿼리 비활성화
enabled 옵션을 콜백으로 설정하면 상태와 네비게이션 시 재렌더링 없이 포커스를 잃은 화면에서 쿼리를 비활성화할 수 있습니다. 이는 notifyOnChangeProps와 유사하게 작동하지만, refetchType이 active인 쿼리를 무효화할 때 다시 가져오기를 트리거하지 않습니다.
import React from 'react' import { useFocusEffect } from '@react-navigation/native' export function useQueryFocusAware(notifyOnChangeProps?: NotifyOnChangeProps) { const focusedRef = React.useRef(true) useFocusEffect( React.useCallback(() => { focusedRef.current = true return () => { focusedRef.current = false } }, []), ) return () => focusRef.current useQuery({ queryKey: ['key'], queryFn: () => fetch(...), enabled: () => focusedRef.current, }) }
typescript
이렇게 React Native 환경에서 React Query를 효과적으로 사용할 수 있습니다. 온라인 상태 관리, 앱 포커스 시 다시 가져오기, 화면 포커스 시 새로 고침 등의 기능을 활용하여 앱의 성능과 사용자 경험을 향상시킬 수 있습니다.