[React Native] 리액트 네이티브에서 데이터 무효화와 새로고침 기능을 제공하는 useRefreshing hook 소개
React Native의 FlatList, ScrollView 와 같은 컴포넌트에는 refreshControl 속성이 있습니다. 이 prop을 사용하면 사용자가 스크린을 아래로 내릴 때 (Swiping Down) 리스트를 새로고침할 수 있는 기능을 구현할 수 있습니다.
해당 기능은 refreshControl이라는 속성에서 제공되는데요. 자세한 기본 설명은 React Native 문서를 참고해주세요.
이번 글에서는 refreshControl를 구현하기 위해 생성한 useRefreshing이라는 커스텀 훅에 대해 알아보겠습니다. 이 훅은 리액트 쿼리(Query)를 무효화하고 새로고침하는 기능을 제공하여 애플리케이션의 데이터 관리를 향상시킵니다.
useRefreshing 의 기능과 목적
useRefreshing 훅은 다음과 같은 목적을 가지고 있습니다:
- 리액트 컴포넌트에서 데이터를 무효화(invalidate)하고 새로고침(refresh)할 수 있는 기능 제공
- useInvalidateQuires 훅(커스텀 훅)을 사용하여 리액트 쿼리(Query)를 무효화하는 로직 구현
- 새로고침 상태를 관리하여 UI 업데이트를 제어하는 상태 관리
아래는 useRefresh hook 의 전체 코드입니다.
import React, { useCallback, useMemo, useState } from 'react';
import { QueryKey } from '@tanstack/react-query';
import { isArrayWithNestedArrays } from '@utils/validate/has-nested-array';
import { wait } from '@utils/wait';
import useInvalidateQuires from './useInvalidateQuires';
const useRefreshing = () => {
const invalidateQueries = useInvalidateQuires();
const [isRefresh, setIsRefresh] = useState(false);
const onRefresh = useCallback(
async (queryKeys: QueryKey[] | QueryKey) => {
if (!queryKeys) return;
setIsRefresh(true);
try {
await wait(200);
if (isArrayWithNestedArrays(queryKeys)) {
invalidateQueries.multiple(queryKeys);
} else {
invalidateQueries.single(queryKeys);
}
} catch (err) {
console.log('err', err);
} finally {
setIsRefresh(false);
}
},
[invalidateQueries],
);
return useMemo(() => ({ onRefresh, isRefresh }), [onRefresh, isRefresh]);
};
export default useRefreshing;
주요 함수 설명
onRefresh()
onRefresh 함수는 리액트 컴포넌트에서 호출되는 콜백 함수입니다. 이 함수는 queryKeys라는 인자를 받아와 새로고침 동작을 수행합니다. 새로고침이 시작되면 setIsRefresh(true)를 호출하여 isRefresh 상태를 true로 변경하고, 200밀리초의 딜레이(`wait(200)`) 이후에 쿼리를 무효화합니다.
queryKeys가 배열이고 중첩 배열을 포함하는 경우 쿼리 무효화 커스텀 훅인`invalidateQueries.multiple`을 호출하고, 그렇지 않은 경우 `invalidateQueries.single`을 호출합니다. Custom hook : invalidateQueries 글 이동
모든 동작이 완료되면(finally) isRefresh 상태를 항상 false로 변경하도록 하였습니다. 이를 통해 비동기 작업이 성공적으로 완료되거나 실패하더라도 새로고침 상태가 정확하게 업데이트됩니다.
사용 예시
useRefreshing 훅을 사용하여 onRefresh와 isRefresh를 가져옵니다. 이를 활용하여 FlatList 컴포넌트의 refreshControl prop을 설정합니다. 사용자가 리스트를 당겨서 새로고침할 수 있는 기능이 구현되며, isRefresh 상태에 따라 적절한 인디케이터를 표시합니다.
import React from 'react';
import { View, Text, FlatList, RefreshControl } from 'react-native';
import useRefreshing from './useRefreshing';
const MyComponent = () => {
const { onRefresh, isRefresh } = useRefreshing();
// 데이터 로딩 및 뷰 렌더링 로직
return (
<View>
<FlatList
data={data}
renderItem={({ item }) => <Text>{item.name}</Text>}
keyExtractor={(item) => item.id}
refreshControl={
<RefreshControl refreshing={isRefresh} onRefresh={() => onRefresh(queryKey)} />
}
/>
</View>
);
};
export default MyComponent;
이렇게 useRefreshing 훅을 사용하면 React Native 애플리케이션에서 refreshControl을 손쉽게 구현할 수 있습니다. 사용자가 리스트나 뷰를 새로고침할 수 있도록 하여 좋은 사용자 경험을 제공할 수 있습니다.