이 포스트는 Expo 환경에서 작성되어 있지만 모든 React Native 환경에서 적용되는 내용입니다. 또한, 기본적인 셋팅이 되어있는 프로젝트를 기준으로 작성되었습니다.
ActivityIndicator
와 react-native-skeleton-placeholder
를 사용해보겠습니다. ActivityIndicator
는 기본적으로 제공되는 원 형태의 로딩 Indicator이며, react-native-skeleton-placeholder
는 뼈대를 빈 상태로 미리 보여주는 Indicator입니다. 상황에 따라 적절한 Indicator를 사용하면 사용자에게 더 나은 경험을 제공할 수 있습니다.App.js
파일을 열어 다음과 같이 코드를 작성합니다. 이 코드는 사용자가 화면을 새로고침할 때마다 2초 후에 현재 시간을 표시하는 화면을 만드는 코드입니다. 새로고침 작동 원리는 react native refreshcontrol 포스트를 참고해주세요.import React, { useEffect, useState } from 'react';
import { Text, ScrollView, RefreshControl, View, SafeAreaView } from 'react-native';
const Card = () => {
const [now, setNow] = useState('');
useEffect(() => {
setTimeout(() => {
setNow(new Date().toLocaleString());
}, 2000);
}, []);
return (
<View style={{ flex: 1 }}>
{Array.from({ length: 100 }).map((_, index) => (
<Text key={index} style={{ textAlign: 'center', justifyContent: 'center', fontSize: 20 }}>{`${now}`}</Text>
))}
</View>
);
};
const List = () => {
const [key, setKey] = useState(new Date().getTime());
const [refreshing, setRefreshing] = useState(false);
const handleRefresh = () => {
setRefreshing(true);
setKey(new Date().getTime());
setRefreshing(false);
};
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'white', padding: 20 }}>
<ScrollView
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={handleRefresh} colors={['blue', 'red', 'green']} />
}
>
<View style={{ flex: 1, flexDirection: 'row' }}>
<Card key={key} />
</View>
</ScrollView>
</SafeAreaView>
);
};
export default List;
ActivityIndicator
는 기본적으로 제공되는 컴포넌트이기 때문에 별도의 설치가 필요하지 않습니다. ActivityIndicator
를 사용하려면 다음과 같이 코드를 작성하면 됩니다.
새로고침 Indicator과 분리하기 위해 파란색으로 설정했습니다. 데이터를 불러오는 동안에만 Indicator가 보이도록 하기 위해 isLoading
상태를 추가했습니다.import React, { useEffect, useState } from 'react';
import { Text, ScrollView, RefreshControl, View, SafeAreaView, ActivityIndicator } from 'react-native';
const Card = () => {
const [now, setNow] = useState('');
const [isLoading, setIsLoading] = useState(true); // isLoading 추가
useEffect(() => {
setIsLoading(true); // 데이터 로딩 시작
setTimeout(() => {
setNow(new Date().toLocaleString());
setIsLoading(false); // 데이터 로딩 완료
}, 2000);
}, []);
return (
<View style={{ flex: 1 }}>
{isLoading ? (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', height: 200 }}>
<ActivityIndicator size="large" color="blue" /> // ActivityIndicator 추가
</View>
) : (
Array.from({ length: 100 }).map((_, index) => (
<Text key={index} style={{ textAlign: 'center', justifyContent: 'center', fontSize: 20 }}>{`${now}`}</Text>
))
)}
</View>
);
};
const List = () => {
const [key, setKey] = useState(new Date().getTime());
const [refreshing, setRefreshing] = useState(false);
const handleRefresh = () => {
setRefreshing(true);
setKey(new Date().getTime());
setRefreshing(false);
};
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'white', padding: 20 }}>
<ScrollView
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={handleRefresh} colors={['blue', 'red', 'green']} />
}
>
<View style={{ flex: 1, flexDirection: 'row' }}>
<Card key={key} />
</View>
</ScrollView>
</SafeAreaView>
);
};
export default List;
react-native-skeleton-placeholder
는 뼈대를 빈 상태로 미리 보여주는 Indicator입니다. react-native-skeleton-placeholder
를 사용하려면 먼저 설치해야 합니다. 다음 명령어를 둘 중 하나 실행하여 설치합니다.npm install @react-native-masked-view/masked-view react-native-linear-gradient --save
npm install react-native-skeleton-placeholder --save
yarn add @react-native-masked-view/masked-view react-native-linear-gradient
yarn add react-native-skeleton-placeholder
react-native-skeleton-placeholder
를 사용하려면 다음과 같이 코드를 작성하면 됩니다.
import React, { useEffect, useState } from 'react';
import { Text, ScrollView, RefreshControl, View, SafeAreaView } from 'react-native';
import SkeletonPlaceholder from 'react-native-skeleton-placeholder';
const Card = () => {
const [now, setNow] = useState('');
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
setIsLoading(true);
setTimeout(() => {
setNow(new Date().toLocaleString());
setIsLoading(false);
}, 2000);
}, []);
return (
<View style={{ flex: 1 }}>
{isLoading ? (
<SkeletonPlaceholder borderRadius={4}>
<Text style={{ marginTop: 6, fontSize: 14, lineHeight: 18 }}>Hello world</Text>
</SkeletonPlaceholder>
) : (
Array.from({ length: 100 }).map((_, index) => (
<Text key={index} style={{ textAlign: 'center', justifyContent: 'center', fontSize: 20 }}>{`${now}`}</Text>
))
)}
</View>
);
};
const List = () => {
const [key, setKey] = useState(new Date().getTime());
const [refreshing, setRefreshing] = useState(false);
const handleRefresh = () => {
setRefreshing(true);
setKey(new Date().getTime());
setRefreshing(false);
};
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'white', padding: 20 }}>
<ScrollView
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={handleRefresh} colors={['blue', 'red', 'green']} />
}
>
<View style={{ flex: 1, flexDirection: 'row' }}>
<Card key={key} />
</View>
</ScrollView>
</SafeAreaView>
);
};
export default List;
ERROR Warning: TypeError: Cannot read property 'bubblingEventTypes' of null
에러가 있어 이를 해결하는 방법을 찾고 있습니다. 이에 대한 해결 방법을 찾으면 업데이트하겠습니다.
github issue↗