[플러터] 12. setState

백하림's avatar
May 29, 2025
[플러터] 12. setState

전체 rebuild

import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: HomePage(), ); } } class HomePage extends StatefulWidget { @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { // 1. 상태 int num = 1; // 2. 행위 void increase() { num++; setState(() {}); // rebuild } @override Widget build(BuildContext context) { print("rebuild 됨"); return Scaffold( appBar: AppBar(), body: Center( child: Text("${num}", style: TextStyle(fontSize: 50)), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: increase, ), ); } }
notion image

전체 rebuild

🔥
  1. 분리 없이 코드를 작성했음
  1. 증가 버튼을 누르면 숫자가 증가됨
  1. 원하는 건 부분 rebuild인데 지금은 전체가 rebuild 되고 있음
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: HomePage(), ); } } class HomePage extends StatefulWidget { @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { int num = 1; @override Widget build(BuildContext context) { return Container( color: Colors.yellow, child: Padding( padding: const EdgeInsets.all(20.0), child: Column( children: [ Expanded( child: Container( color: Colors.red, child: Align( child: Text( "${num}", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 100, decoration: TextDecoration.none), ), ), ), ), Expanded( child: Container( color: Colors.blue, child: Align( child: ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.red), onPressed: () { num++; setState(() {}); }, child: Text( "증가", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 100, ), ), ), ), ), ), ], ), ), ); } }
notion image

전체 rebuild

🔥
context를 분리하니까 상태가 있는 쪽에서 행위를 가져야 하는데 행위는 바텀에서 가지고 있음
위에 상태를 변경하기 위해서 바텀에서 행위를 가져야 하는데 가질 수가 없음
그래서 결국 부모가 스테이트 풀이 되고 전체 리로드 됨
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: HomePage(), ); } } class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { int num = 1; void increase() { num++; setState(() {}); } @override Widget build(BuildContext context) { return Container( color: Colors.yellow, child: Padding( padding: const EdgeInsets.all(20), child: Column( children: [ Expanded(child: HeaderPage(num)), Expanded(child: const MiddlePage(1)), Expanded(child: const MiddlePage(1)), Expanded(child: BottomPage(increase)), ], ), ), ); } } class HeaderPage extends StatelessWidget { int num; HeaderPage(this.num); @override Widget build(BuildContext context) { print("header"); return Container( color: Colors.red, child: Align( child: Text( "${num}", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 100, decoration: TextDecoration.none), ), ), ); } } class BottomPage extends StatelessWidget { Function increase; BottomPage(this.increase); @override Widget build(BuildContext context) { print("bottom"); return Container( color: Colors.blue, child: Align( child: ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.red), onPressed: () { print("버튼 클릭됨"); increase(); }, child: Text( "증가", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 100, ), ), ), ), ); } } class MiddlePage extends StatelessWidget { final num; const MiddlePage(this.num); @override Widget build(BuildContext context) { return Container( color: Colors.white, ); } }
notion image

부분 rebuild

🔥
진짜 부모 (MyApp, HomePage - Stateless) └─ 가짜 부모 (Middle - Stateful) ├─ 상태 자식 (Top) ├─ 중간 자식 (→ 없음 또는 상태 전달만) └─ 행위 자식 (Bottom - 버튼)
행위 위젯(Bottom)이 호출한 함수는 상태를 가진 중간 위젯(Middle)에서 setState()를 실행시키고, 이로 인해 중간 위젯만 리렌더링되며, 상태값을 전달받은 상태 위젯(Top)만 실제 UI가 변경됨.
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: HomePage(), ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { print("홈페이지 빌드"); return Scaffold( body: Middle(), ); } } // 가짜 부모 << 혼자만 Stateful 이다 class Middle extends StatefulWidget { const Middle({ super.key, }); @override State<Middle> createState() => _MiddleState(); } class _MiddleState extends State<Middle> { int num = 1; void increase() { num++; setState(() {}); } @override Widget build(BuildContext context) { return Column( children: [ Expanded( child: Top(num), ), Expanded( child: Bottom(increase), ), ], ); } } class Bottom extends StatelessWidget { Function increase; Bottom(this.increase); @override Widget build(BuildContext context) { return Center( child: Container( child: ElevatedButton( onPressed: () { increase(); }, child: Icon(Icons.add), ), ), ); } } class Top extends StatelessWidget { int num; Top(this.num); @override Widget build(BuildContext context) { return Center( child: Container( child: Text("$num", style: TextStyle(fontSize: 50)), ), ); } }
notion image
 
Share article

harimmon