เก็บสเตตไว้ในบรรพบุรุษร่วม แล้วเปลี่ยนวิดเจ็ตลูกของคุณให้เป็นวิดเจ็ตแบบควบคุมที่รายงานการเปลี่ยนแปลงกลับขึ้นไปผ่านคอลแบ็ก
เปิดบทเรียนนี้ใน Kodokonสถานการณ์คลาสสิก ตัวเลือกจำนวน (quantity selector) กับยอดรวมที่แสดงอยู่ที่อื่นจำเป็นต้องใช้ข้อมูลชุดเดียวกัน กฎทองคำคือ สเตตอยู่ใน บรรพบุรุษร่วมที่ใกล้ที่สุด ของวิดเจ็ตที่พึ่งพามัน วิดเจ็ตแม่เป็นเจ้าของข้อมูล ส่งมันลงไปเป็นพารามิเตอร์ และรับการเปลี่ยนแปลงผ่าน คอลแบ็ก ที่ไหลย้อนกลับขึ้นมา นี่คือสิ่งที่เรียกว่า "การยกสเตตขึ้น" (lifting state up)
import 'package:flutter/material.dart';
class CartScreen extends StatefulWidget {
const CartScreen({super.key});
@override
State<CartScreen> createState() => _CartScreenState();
}
class _CartScreenState extends State<CartScreen> {
int _quantity = 1;
void _updateQuantity(int value) {
setState(() => _quantity = value);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Cart')),
body: Column(
children: [
QuantitySelector(
quantity: _quantity,
onChanged: _updateQuantity,
),
Text('Total: ${_quantity * 20} €'),
],
),
);
}
}วิดเจ็ตลูกกลายเป็น วิดเจ็ตแบบควบคุม มันเป็น StatelessWidget ไม่เก็บอะไรไว้เลย แสดงค่าที่มันได้รับ และส่งสัญญาณความตั้งใจแต่ละครั้งผ่าน onChanged โดย ValueChanged<int> ก็เป็นเพียงชื่อแทน (alias) ของ void Function(int) สังเกตปุ่มลบที่ถูกปิดใช้งานเมื่อจำนวนเท่ากับ 1 เพียงส่ง null ให้ onPressed ก็เพียงพอ และตรรกะนี้สืบเนื่องมาจากค่าที่ได้รับโดยตรง
import 'package:flutter/material.dart';
class QuantitySelector extends StatelessWidget {
const QuantitySelector({
super.key,
required this.quantity,
required this.onChanged,
});
final int quantity;
final ValueChanged<int> onChanged;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.remove),
onPressed: quantity > 1
? () => onChanged(quantity - 1)
: null,
),
Text('$quantity'),
IconButton(
icon: const Icon(Icons.add),
onPressed: () => onChanged(quantity + 1),
),
],
);
}
}คุณใช้ข้อตกลงนี้อยู่ตลอดเวลาโดยไม่รู้ตัว Checkbox, Slider, Switch ล้วนเป็นวิดเจ็ตแบบควบคุมทั้งสิ้น (value + onChanged) เมื่อทรีลึกลงและการร้อยคอลแบ็กผ่านห้าระดับเริ่มน่าเบื่อ ก็จะถึงเวลาที่ต้องรู้จักโซลูชันการจัดการสเตต ซึ่งเป็นหัวข้อของโมดูลถัดไป