Flet Best Practices¶
Critical Rules¶
1. SafeArea is Mandatory¶
Every page and view MUST use ft.SafeArea:
# ✅ CORRECT
ft.SafeArea(
content=ft.Column([...]),
expand=True
)
# ❌ WRONG - will not work correctly on mobile
ft.Column([...])
2. Check Documentation Before Using Controls¶
- Go to:
https://flet.dev/docs/controls/<component_name_lowercase> - Read properties, events, and deprecated warnings
- Verify you're not using deprecated APIs
- Check the platform support
3. Deprecated APIs to Avoid¶
| Deprecated | Use Instead |
|---|---|
ft.border_radius.only() |
ft.BorderRadius.only() |
page.get_string() |
page.get() |
page.set_string() |
page.set() |
Container.padding with tuple |
Container.padding=ft.Padding(...) |
Async Patterns¶
Correct Pattern for Async Callbacks¶
# ❌ WRONG - coroutine never awaited
on_click=lambda e: page.show_drawer()
# ✅ CORRECT - use run_task with async method
on_click=lambda e: page.run_task(self._open_drawer_async)
async def _open_drawer_async(self):
await page.show_drawer()
Entry Point¶
ALWAYS use:
NEVER use:
State Management¶
# Use reactive state with page.manager
class MyPage:
def __init__(self, page):
self.page = page
self._counter = 0
def build(self):
return ft.Column([
ft.Text(f"Count: {self._counter}"),
ft.Button("Add", on_click=self._increment)
])
def _increment(self, e):
self._counter += 1
self.page.update()
Common Mistakes¶
Wrong: Using Container.padding as tuple¶
# ❌ This will fail
Container(padding=(10, 20, 10, 20))
# ✅ Correct
Container(padding=ft.Padding(10, 20, 10, 20))
Wrong: Not handling resize on web¶
# ✅ Use expand=True and SafeArea properly
ft.SafeArea(
expand=True,
content=ft.Column([], scroll=ft.ScrollMode.AUTO)
)
Performance Tips¶
- Avoid unnecessary page.update() - Only update when state changes
- Use controls' expand property - Don't set explicit heights when possible
- Lazy load images - Use
loading="lazy"on Image controls - Minimize nested containers - Flatten UI structure when possible