Same vs Different: ตาราง Lookup
นี่คือ cheat sheet ของคุณ คอลัมน์ซ้ายแสดงสิ่งที่คุณรู้จาก React คอลัมน์ขวาแสดง Flutter equivalent รายการส่วนใหญ่ map แบบ one-to-one สิ่งที่แตกต่างจริงๆ จะมีหมายเหตุกำกับ
แผนที่ Concept
หัวข้อที่มีชื่อว่า “แผนที่ Concept”| React concept | Flutter equivalent | หมายเหตุ |
|---|---|---|
| Function component | StatelessWidget | Class ที่มี method build() |
| Class component | StatefulWidget + State<T> | แยกเป็นสอง class |
| Props | Constructor parameters | Dart named params: MyWidget(name: 'Ava') |
useState | setState(() { ... }) | อยู่ใน State<T> subclass |
useEffect (mount) | initState() | เรียกครั้งเดียวหลัง build แรก |
useEffect (unmount) | dispose() | Clean up controllers, streams, timers |
useEffect (deps) | Manual didUpdateWidget / Riverpod | ไม่มี equivalent ตรงๆ |
useContext / Context | InheritedWidget / Provider package | Provider คือ community standard |
React.memo | const constructor | Dart const ป้องกัน rebuild |
key prop | Key / super.key | วัตถุประสงค์เดียวกัน — tree reconciliation |
| JSX | Dart constructor calls | <Text> → Text('...') |
| CSS / StyleSheet | Widget params + ThemeData | TextStyle, BoxDecoration ฯลฯ |
| Flexbox | Row / Column | mainAxisAlignment ≈ justify-content |
display: none | Conditional ด้วย if หรือ Visibility | if (show) MyWidget() ใน children list |
| react-router / Next.js | Navigator + routes / go_router | Imperative หรือ declarative routing |
| npm / package.json | pub / pubspec.yaml | flutter pub add package_name |
| Fast Refresh | Hot Reload (r ใน terminal) | เก็บ state ไว้; hot restart = full reload |
.map() ใน JSX | .map(...).toList() ใน children | Return List<Widget> |
styled-components | ThemeData + widget params | ไม่มี runtime CSS — เป็น Dart compile-time ทั้งหมด |
React.createContext | InheritedWidget หรือ ChangeNotifier | Provider wrap ทั้งสอง pattern |
ความแปลกใจสองอันดับแรก
หัวข้อที่มีชื่อว่า “ความแปลกใจสองอันดับแรก”// React instinct — what you'd reach forfunction ProfileCard({ name, isAdmin }) { const [liked, setLiked] = useState(false); return ( <div className="card" style={{ padding: 16, borderRadius: 12 }}> <h3 style={{ margin: 0 }}>{name}</h3> {isAdmin && <span className="badge">Admin</span>} <button onClick={() => setLiked(l => !l)}> {liked ? '❤️ Liked' : '🤍 Like'} </button> </div> );}// Flutter equivalent — layout is widgetsclass ProfileCard extends StatefulWidget { final String name; final bool isAdmin; const ProfileCard({super.key, required this.name, this.isAdmin = false});
@override State<ProfileCard> createState() => _ProfileCardState();}
class _ProfileCardState extends State<ProfileCard> { bool _liked = false;
@override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(widget.name, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), if (widget.isAdmin) Container( margin: const EdgeInsets.only(top: 4), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: Colors.blue[100], borderRadius: BorderRadius.circular(4), ), child: const Text('Admin', style: TextStyle(color: Colors.blue, fontSize: 12)), ), const SizedBox(height: 8), GestureDetector( onTap: () => setState(() => _liked = !_liked), child: Text( _liked ? '❤️ Liked' : '🤍 Like', style: const TextStyle(fontSize: 16), ), ), ], ), ); }}