들어가기 앞서...
이번 게시글에는 저번 작업물에서 상태관리한것을 최상위로 올릴것이다.
최상위로 올려야하는 이유는 데이터 관리 하는 것이 여러 군데로 나눠져있으면 데이터의 흐름도를 보기가 굉장히 힘들어지고,
수정을 하려고하면 어디에서 어떤데이터를 다루는 지 찾아야하는게 힘들어진다. 즉 코드관리가 어려워진다.
그래서 우리가 상태관리를 모든 위젯들이 속해있는 최상위 트리인 HomeScreen 클래스로 관리를 해주면 우리가 데이터를 보내주기 쉽다.
만약 데이터 관리해주는게 많아지면 StatefulWidget 만으로는 힘들어진다. 나중에는 상태관리 툴을 사용할 것이다.
1. 주의 깊게 봐야하는 점...
- 상태관리는 상위 위젯에서 한번에 관리 해주는 것이 가독성이 좋고 코드 추가, 수정에도 용이하다.
- StatefulWidget로 작성된 하위 위젯으로는 데이터를 상위 위젯에서 하위위젯으로 데이터를 내려주는 것이 불가능하다. 그러니 StatefulWidget을 StatelessWidget으로 바꿔서 상태관리를 상위 위젯에서 진행해보도록 하자!
본문으로...
1. StatefulWidget을 StatelessWidget으로 변경을 해보자!
- _TopPart 클래스를 삭제해주고, _TopPartState 클래스의 State<_TopPart> 를 SatelessWidget으로 변경해주고 클래스 이름도 헷갈리지 않게 변경해준다.
그리고 코드들을 하나씩 옮겨준다.
그러면 굉장히 많이 에러가 날 것이다.
2. constructor 를 만들어주자!
- selectedDate 를 못찾는 에러, StatefulWidget 에서만 사용이 가능한 setSate 에러 이다.
constructor 를 하나 만들어서 필수키로 selectedDate 를 파라미터로 받아주고, 받아온 selectedDate 를 저장할 변수를 하나 선언해준다. 그렇다면 위의 selectedDate에 대한 에러 표시는 사라질 것이다. setState 에러 표시는 잠시 후에 진행하자!
class _TopPart extends StatelessWidget {
final DateTime seletedDate;
_TopPart({required this.selectedDate, Key? key}): super(key: key);
...
}
3. HomeScreen 에서 필수 파라미터인 selectedDate 를 내려주자!
class _HomeScreenState extends State<HomeScreen> {
...
child: Column(
children: [
_TopPart(
selectedDate: selectedDate,
),
_BottomPart(),
]
)
...
}
4. setSate({}) 에러 표시해결하자!
- setSate() 는 StatefulWidget에서만 존재하며, 사용 가능 한것이다. 현재는 상태관리를 트리에 최상단으로 올리기 위해서 SatefulWidget -> StatelessWidget 으로 변경을 해준것이다. 그래서 에러 표시가 나는 것인다. 해결방법은 onDateChanged 가 될때, 파라미터만 외부에서 받아오면 해결이 되는데, 더 간단하게, 그 보다 더 위의 위젯인 onPressed 전체를 상위 위젯으로 옮길것이다.
1 ) onPressed 함수를 Go to Declaration or Usages(command + B) 를 해주자
2) 만약에 VoidCallback onPressed 라는 타입을 받으면, onPressed 를 바로 IConButton 에 파라미터로 전달해주면 상위 위젯에서 정의가 가능해진다. 그러면 setState도 실행이 가능해진다.
5. 상위위젯에서 파라미터로 onPressed 를 내려줄것이고, 내려준 onPressed 를 저장할 변수를 선언해준다!
...
class _TopPart extends StatelessWidget {
final DateTime selectedDate;
// 추가
final VoidCallback onPressed;
_TopPart({required this.selectedDate, required this.onPressed, Key? key})
: super(key: key);
...
IconButton(
...
onPressed: onPressed,
...
),
...
}
...
6. 상위위젯인 Sate클래스에서 onPressed를 파라미터로 내려주고, 새로운 함수 하나 만들어서 기존 onPressed 함수 붙여넣기!
class _HomeScreenState extends State<HomeScreen> {
...
child: Column(
children: [
_TopPart(
selectedDate: selectedDate,
// 추가
onPressed: onHeartPressed,
)
]
),
...
}
// 기존 onPressed () 붙여넣기
void onHeartPressed() {
final DateTime now = DateTime.now();
showCupertinoDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.white,
height: 300.0,
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
initialDateTime: selectedDate,
maximumDate: DateTime(
now.year,
now.month,
now.day,
),
onDateTimeChanged: (DateTime date) {
setState(() {
selectedDate = date;
});
},
),
),
);
});
}
}
_TopPart() 함수에 파라미터로 그대로 복붙 해줄 수 있는데, 그러면 코드가 너무 길어지고 가독성이 떨어지므로 새로운 함수 onHeartPressed 를 만들어 넣어주자!
7. 완성
이전 과 기능은 같지만, 상태관리를 HomeScreen 에서 상태관리를 해서 하위위젯에 파라미터로 내려주는 방식으로 바꿔주었다.
- 장정 : 다른 위젯이나, _BottomPart() 에 파라미터를 추가해주거나, 다른 위젯에서 데이터를 공유해줘야할 경우에는_TopPart()를 stful 로 만들어서 데이터 흐름을 이렇게 만들 수 없다. 왜냐하면 자식에서 부모로 상태값을 파라미터로 전달해줄 수 없기 때문이다.
- 단점 : 지금은 코드가 복잡해 보일 수 있다.
끝으로...
- 최상단 위젯에서 상태관리 하는 방법을 배웠고 장점을 알았다!

'⭐️ 개발 > 플러터' 카테고리의 다른 글
[패캠-코딩 왕초보를 위한 앱 만들기 풀패키지] (5) StatefulWidget, FloatingActionButton (0) | 2022.11.15 |
---|---|
[프로젝트] 우리 처음 만난날 U&I (5) 테마 적용 (0) | 2022.11.10 |
[패캠-코딩 왕초보를 위한 앱 만들기 풀패키지] (2) 복수 위젯담는 박스 (0) | 2022.11.09 |
[패캠-코딩 왕초보를 위한 앱 만들기 풀패키지] (1) padding, margin, alignment (0) | 2022.11.09 |
[프로젝트] 우리 처음 만난날 U&I (3) DateTime 관리 (0) | 2022.11.07 |