이 포스트는 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 --saveyarn add @react-native-masked-view/masked-view react-native-linear-gradient
yarn add react-native-skeleton-placeholderreact-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↗