아직 조금 적응이 안되긴 하는데 한번 작성해보겠다! 우선 우리가 알아야 할 정보
이전 포스팅 에서도 게시했지만 model 부분은 빼고 보기 좋게 초기 설정 코드만 작성 해보겠다.
final shoppingListProvider =
StateNotifierProvider<ShoppingListNotifier, List<ShoppingItemModel>>(
(ref) => ShoppingListNotifier(),
);
class ShoppingListNotifier extends StateNotifier<List<ShoppingItemModel>> {
ShoppingListNotifier()
: super(
[
ShoppingItemModel(
name: '김치',
quantity: 3,
hasBought: false,
isSpicy: true,
),
ShoppingItemModel(
name: '라면',
quantity: 5,
hasBought: false,
isSpicy: true,
),
ShoppingItemModel(
name: '삼겹살',
quantity: 10,
hasBought: false,
isSpicy: false,
),
ShoppingItemModel(
name: '수박',
quantity: 2,
hasBought: false,
isSpicy: false,
),
ShoppingItemModel(
name: '카스테라',
quantity: 5,
hasBought: false,
isSpicy: false,
),
],
);
void toggleHasBought({required String name}) {
state = state
.map((e) => e.name == name
? ShoppingItemModel(
name: e.name,
quantity: e.quantity,
hasBought: !e.hasBought,
isSpicy: e.isSpicy,
)
: e)
.toList();
}
}
상태가 하나 정의되어 있다.
오늘 해볼 것은 Provider 안에서 Provider! 한번 진행 해보겟다!
final filterListProvider = Provider((ref) =>
ref.watch(shoppingListProvider));
간단하게 상태를 하나 만들어준다.
class ProviderScreen extends ConsumerWidget {
const ProviderScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(filterListProvider);
return DefaultLayout(
title: 'ProviderScreen',
body: ListView(
children: state
.map(
(e) => CheckboxListTile(
title: Text(e.name),
value: e.hasBought,
onChanged: (value) {
ref.read(shoppingListProvider.notifier).toggleHasBought(name: e.name);
},
),
)
.toList(),
),
);
}
}
간단하게 코드 설명하면 미리 Component로 만든 DefaultLayout 파일이 있으며, 해당 코드로 작성 했을 경우
이미지 처럼 결과물이 나오는 것을 확인할 수 있다.
이번에는 AppBar 에다가 PopupButton을 만들어 보겠다.
enum FilteredState {
spicy,
notSpicy,
all
}
final spicyProvider = StateProvider((ref) => FilteredState.all);
만들어 준 후,
actions: [
PopupMenuButton(
itemBuilder: (_) => FilteredState.values
.map(
(e) => PopupMenuItem(
value: e,
child: Text(e.name),
),
)
.toList(),
),
],
AppBar actions 에다가 넣어준다.
이미지와 같이 정상 작동되는 것을 알수 있다.
PopupMenuButton(
itemBuilder: (_) => FilteredState.values
.map(
(e) => PopupMenuItem(
value: e,
child: Text(e.name),
),
)
.toList(),
onSelected: (value) {
print(value);
},
),
onSelected 부분을 추가해서 print 를 확인하면
flutter: FilteredState.notSpicy
flutter: FilteredState.spicy
flutter: FilteredState.all
이런식으로 찍히는 것을 볼수있다. 상태를 변경해보자!
onSelected: (value) {
ref.read(spicyProvider.notifier).update((state) => value);
},
이제 팝업으로 값을 변경할수 있다.
추가 동작 우리는 이제 spicy 음식과 notSpicy 음식으로 filter를 해볼것이다.
final filterListProvider = Provider((ref) {
final filterState = ref.watch(spicyProvider);
final shoppingListState = ref.watch(shoppingListProvider);
if (filterState == FilteredState.all) {
return shoppingListState;
}
return shoppingListState.where((element) => filterState == FilteredState.spicy ? element.isSpicy : !element.isSpicy).toList();
});
enum FilteredState {
spicy,
notSpicy,
all
}
final spicyProvider = StateProvider((ref) => FilteredState.all);
filterState 는 spicyProvider , select 로 변경한 값을 계속 주시한다.
shoppingListState 는 기존에도 사용하던 쇼핑리스트다.
spicy 를 골랐을 경우 김치와 라면이 잘나오는 것을 볼수있다. 오늘 뭔가 어려우면서 재밌는 관리를 한거같다.