1. React Native
React Query๋ React DOM์์๋ง ์ง์๋๋ DevTools๋ฅผ ์ ์ธํ๊ณ ๋์ํ๋ค.
์๋ํด ๋ณผ ๋งํ ์๋ํํฐ Flipper ํ๋ฌ๊ทธ์ธ์ด ์๋ค https://github.com/bgaleotti/react-query-native-devtools
์๋ํด ๋ณผ ๋งํ ์๋ํํฐ Reactotron ํ๋ฌ๊ทธ์ธ์ด ์๋ค. https://github.com/hsndmr/reactotron-react-query
๐ก ์๋ํํฐ(Third Party)์ ์ฌ์ ์ ์ ์๋ โ์ 3์โ๋ฅผ ์๋ฏธ
IT์ ๊ณ์์ ์๋ํํฐ๋ ์ด๋ ํ ๋ถ์ผ์์ ์ฒ์ ๊ฐ๋ฐํ๊ฑฐ๋ ์์ฒ๊ธฐ์ ์ ๊ฐ์ง๊ณ ์๋ ๊ฒ ์๋, ์์ฒ๊ธฐ์ ๊ณผ ํธํ๋๋ ์ํ์ ์ถ์ํ๊ฑฐ๋ ํด๋น ๊ธฐ์ ์ ์ด์ฉํ ํ์์ํ์ ์์ฐํ๋ ํ์ฌ
2. ์จ๋ผ์ธ ์ํ ๊ด๋ฆฌ
React Query๋ ์ด๋ฏธ ์น ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฐ๊ฒฐ ์ ์๋ ์ฌ์ค์ ์ ์ง์ํ๋ค.
React Native์์๋ ์ถ๊ฐํ๋ ค๋ฉด, ์๋ ์์ ๊ฐ์ด React Query onlineManager๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค:
1import NetInfo from '@react-native-community/netinfo'2import { onlineManager } from '@tanstack/react-query'34onlineManager.setEventListener(setOnline => {5return NetInfo.addEventListener(state => {6setOnline(!!state.isConnected)7})8})
3. App focus์์ Refetch
์น์ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋์ ์, React Native๋ AppState module ํตํด focus ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค. AppState โchangeโ ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํด, ์ฑ ์ํ๊ฐ โactiveโ๋ก ๋ณ๊ฒฝ๋ ๋ ์ ๋ฐ์ดํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ ์ ์๋ค:
1import { useEffect } from 'react'2import { AppState, Platform } from 'react-native'3import type { AppStateStatus } from 'react-native'4import { focusManager } from '@tanstack/react-query'56function onAppStateChange(status: AppStateStatus) {7if (Platform.OS !== 'web') {8focusManager.setFocused(status === 'active')9}10}1112useEffect(() => {13const subscription = AppState.addEventListener('change', onAppStateChange)1415return () => subscription.remove()16}, [])
4. Screen focus์์ Refetch
์ผ๋ถ ์ํฉ๋ค์์, React Native Screen์ด ๋ค์ ํฌ์ปค์ฑ๋ ๋, query๋ฅผ refetchํ๊ธฐ๋ฅผ ์ํ ์ ์๋ค. ์ด custom hook์ Screen์ด ๋ค์ ํฌ์ปค์ฑ๋ ๋, ์ ๊ณต๋ refetch ํจ์๋ฅผ ์ ๊ณตํ๋ค.
1import React from 'react'2import { useFocusEffect } from '@react-navigation/native'34export function useRefreshOnFocus<T>(refetch: () => Promise<T>) {5const firstTimeRef = React.useRef(true)67useFocusEffect(8React.useCallback(() => {9if (firstTimeRef.current) {10firstTimeRef.current = false11return12}1314refetch()15}, [refetch]),16)17}
์์ ์ฝ๋์์, refetch๋ () ์ฒ์์ ์๋ต๋๋ค.
(,์๋ํ๋ฉด useFocusEffect๊ฐ screen focus๊ฐ ์ถ๊ฐ๋ mount์์ ์ฝ๋ฐฑ์ ํธ์ถํ๊ธฐ ๋๋ฌธ์,)
5. out of focus Screens์์ re-renders ๋ง๊ธฐ
์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ํฌํจํ ์ผ๋ถ ์ํฉ์์๋,
React Native ํ๋ฉด์ด ํฌ์ปค์ค๋ฅผ ๋ฒ์ด๋ ๋, re-renders์ ์ค์งํ ์ ์๋ค.
์ด๋ฅผ ๋ฌ์ฑํ๊ธฐ ์ํด, NotifyOnChangeProps ์ฟผ๋ฆฌ ์ต์
๊ณผ ํจ๊ป,
@react-navigation/native์ FocusEffect๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ด ์ปค์คํ
Hook์ () NotifyOnChangeProps ์ต์
์ ์ ๊ณตํ๋ค.
(ํ๋ฉด์ด ์ด์ ์ ๋ฒ์ด๋ ๋๋ง๋ค ๋น ๋ฐฐ์ด์ ๋ฐํํ๋)
(NotifyOnChangeProps - ํด๋น ์๋๋ฆฌ์ค์ ๋ํ ์ฌ๋ ๋๋ง์ ํจ๊ณผ์ ์ผ๋ก ๋ง๋)
ํ๋ฉด์ด ๋ค์ ์ด์ (focus)์ ๋ง์ถ ๋๋ง๋ค, ์ฌ์ ์์ผ๋ก ๋์๊ฐ๋๋ค.
1import React from 'react'2import { NotifyOnChangeProps } from '@tanstack/query-core'3import { useFocusEffect } from '@react-navigation/native'45export function useFocusNotifyOnChangeProps(notifyOnChangeProps?: NotifyOnChangeProps) {6const focusedRef = React.useRef(true)78// ์ฌ๊ธฐ9useFocusEffect(10React.useCallback(() => {11focusedRef.current = true1213return () => {14focusedRef.current = false15}16}, []),17)1819return () => {20if (!focusedRef.current) {21return []22}2324if (typeof notifyOnChangeProps === 'function') {25return notifyOnChangeProps()26}2728return notifyOnChangeProps.current29}30}
์ ์ฝ๋์์, useFocusEffect๋ () ์ฌ์ฉ๋๋ค.
(์ฝ๋ฐฑ์กฐ๊ฑด์ผ๋ก ์ฌ์ฉํ ๊ธฐ์ค๊ฐ์ ๋ณ๊ฒฝํ๋๋ฐ,)
์ด ์ธ์(argument)๊ฐ () ๋ณด์ฅํ๊ธฐ ์ํด ์ฐธ์กฐ๋ฅผ ๊ฐ์ผ๋ค.
(๋ฐํ๋ ์ฝ๋ฐฑ์ด ํญ์ ๋์ผํ ์ฐธ์กฐ๋ฅผ ์ ์งํ๋ค๋ ๊ฒ์,)
์ฌ์ฉ ์:
1function MyComponent() {2const notifyOnChangeProps = useFocusNotifyOnChangeProps()34const { dataUpdatedAt } = useQuery({5queryKey: ['myKey'],6queryFn: async () => {7const response = await fetch('https://api.github.com/repos/tannerlinsley/react-query')8return response.json()9},10notifyOnChangeProps,11})1213return <div>DataUpdatedAt: {dataUpdatedAt}</div>14}