image source: flutter.ko-dev
부모 위젯의 state를 참조, 변경하는 법
자기 자신의 state를 업데이트하려면 setState를 쓰면 된다. 하지만 자식이 부모 위젯의 state를 참조 또는 변경하려면 어떻게 해야할까?
스택오버플로우에 질문이 올라왔고 질문자와 55명의 up vote를 받은 답변은 이러했다.
•
옛날 방법: _MyHomePageState의 글로벌 인스턴스를 생성해서 자식 Stateful Widget에서 _myHomePageState.setState로 사용해라.
•
새로운 방법: 글로벌 인스턴스로 생성할 필요 없이 부모 인스턴스를 자식 위젯에 전달해라.
옛날 방법은 글로벌 인스턴스를 생성한다는 점, 새로운 방법은 인스턴스 하나를 통째로 넘긴다는 점에서 둘 다 별로 좋아보이지 않는다. 또한, 바로 위의 부모가 아니라 더 상위 부모의 state를 변경하려면 부모 인스턴스를 계속해서 자식에게 전달(drilling)해야하는 수고스러움이 있다.
findAncestorStateOfType
Returns the State object of the nearest ancestor StatefulWidget widget that is an instance of the given type T (주어진 타입을 가진, 가장 가까운 부모 StatefulWidget의 State 객체를 반환한다.)
부모 위젯의 state를 참조할 수 있도록 하는 flutter api이다. 이게 가장 정도(正道)인 것 같다.
부모 위젯은 사실상 건드릴 게 없고, 자식 위젯만 수정하면 된다. 이렇게 하면 바로 위의 부모 말고도 더 위의 StatefulWidget 부모의 state도 수정할 수 있다.
class Parent extends StatefulWidget {
ParentState createState() => ParentState();
}
class ParentState extends State<Parent> {
int page = 1;
Widget build(BuildContext context) {
return 어쩌구저쩌구위젯();
}
}
Dart
복사
자식 위젯
ParentState parent = context.findAncestorStateOfType<ParentState>(); 코드를 build 메서드에 추가해서 parent에 있는 setState를 사용하면 된다.
class Child extends StatefulWidget {
SearchBar();
ChildState createState() => ChildState();
}
class ChildState extends State<Child> {
Widget build(BuildContext context) {
ParentState parent = context.findAncestorStateOfType<ParentState>();
return BlaBlaButton(text: Text('자식'), onTap: () {
parent.setState() {
parent.page += 1;
}
});
}
}
Dart
복사
스택오버플로우를 보면 notifier 콜백 함수를 자식에게 전달해 부모 위젯의 state를 변경하는 방법도 있다. 하지만 이것도 더 상위의 부모의 state를 바꾸려면 함수를 전달하는 과정에서 drilling해야하고, 부모와 자식 위젯 둘 다 수정해주어야 한다.