user에 로딩 state가 있어야하는가!
| topics | |
| types | |
| tags |
#flutter #state #loading #riverpod
|
User에 로딩 state가 있어야하는가
Splash 스크린 처리
앱 초기 실행 시 사용자 정보를 불러오는 동안 로딩 화면을 보여줘야 한다.
이때 User 상태가 로딩 중인지 알아야 적절한 UI를 보여줄 수 있다.
null 체크만으로는 부족하다
// 나쁜 예 - 로딩 state 없음
class UserState {
final User? user;
}
문제점:
user == null일 때, 이게 "로딩 중"인지 "로그아웃 상태"인지 "에러 발생"인지 구분이 안 된다.
// 좋은 예 - 로딩 state 있음
class UserState {
final User? user;
final bool isLoading;
final String? error;
}
// 또는 AsyncValue 사용
AsyncValue<User?> userState;
어떻게 구현할까
방법 1: 직접 상태 관리
class UserState {
final User? user;
final bool isLoading;
final String? error;
bool get isLoggedIn => user != null && !isLoading;
bool get isInitializing => isLoading && user == null;
}
방법 2: AsyncValue 사용 (Riverpod)
final userProvider = AsyncNotifierProvider<UserNotifier, User?>(() {
return UserNotifier();
});
// UI에서 사용
ref.watch(userProvider).when(
loading: () => LoadingWidget(),
error: (err, stack) => ErrorWidget(err),
data: (user) => user != null ? HomeScreen() : LoginScreen(),
);
왜 AsyncValue를 권장하냐면: 로딩/에러/데이터 세 가지 상태가 이미 정의되어 있다. 직접 만들 필요 없다.
실제 사용 예시
Splash에서 분기 처리
class SplashScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final userState = ref.watch(userProvider);
return userState.when(
loading: () => SplashLoadingWidget(),
error: (e, _) {
// 에러 발생 시 로그인 화면으로
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go('/login');
});
return SplashLoadingWidget();
},
data: (user) {
// 로딩 완료 후 분기
WidgetsBinding.instance.addPostFrameCallback((_) {
if (user != null) {
context.go('/home');
} else {
context.go('/login');
}
});
return SplashLoadingWidget();
},
);
}
}
관련 문서
- AsyncValue vs AsyncData - AsyncValue 상세 설명
- riverpod read listen - Riverpod 상태 구독
- flutter mvvm - 상태 관리 아키텍처