Skip to content

Commit 308c039

Browse files
devin-ai-integration[bot]thomas@reflex.dev
andcommitted
Replace auth example with form validation - better mixin use case
- Remove problematic auth mixin example that requires singleton behavior - Add comprehensive form validation mixin example with error handling - Update common use cases to emphasize form validation over authentication - Form validation is a better mixin pattern as it's naturally reusable Co-Authored-By: thomas@reflex.dev <thomas@reflex.dev>
1 parent 46afda9 commit 308c039

File tree

1 file changed

+74
-32
lines changed

1 file changed

+74
-32
lines changed

docs/state_structure/mixins.md

Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -225,53 +225,95 @@ This pattern allows you to build complex functionality by composing simpler mixi
225225

226226
State mixins are particularly useful for:
227227

228-
- **Authentication**: Shared login/logout functionality
229-
- **Validation**: Common form validation logic
228+
- **Form Validation**: Shared validation logic across forms
229+
- **UI State Management**: Common modal, loading, or notification patterns
230230
- **Logging**: Centralized logging and debugging
231231
- **API Integration**: Shared HTTP client functionality
232-
- **UI State**: Common modal, loading, or notification patterns
232+
- **Data Formatting**: Consistent data presentation across components
233233

234234
```python demo exec
235-
class AuthMixin(rx.State, mixin=True):
236-
is_authenticated: bool = False
237-
username: str = ""
235+
class ValidationMixin(rx.State, mixin=True):
236+
errors: dict[str, str] = {}
237+
is_loading: bool = False
238238

239239
@rx.event
240-
def login(self, username: str):
241-
# Simplified login logic
242-
self.username = username
243-
self.is_authenticated = True
240+
def validate_email(self, email: str) -> bool:
241+
if "@" not in email or "." not in email:
242+
self.errors["email"] = "Invalid email format"
243+
return False
244+
self.errors.pop("email", None)
245+
return True
244246

245247
@rx.event
246-
def logout(self):
247-
self.username = ""
248-
self.is_authenticated = False
248+
def validate_required(self, field: str, value: str) -> bool:
249+
if not value.strip():
250+
self.errors[field] = f"{field.title()} is required"
251+
return False
252+
self.errors.pop(field, None)
253+
return True
249254

250-
class DashboardState(AuthMixin, rx.State):
251-
dashboard_data: list[str] = []
255+
@rx.event
256+
def clear_errors(self):
257+
self.errors = {}
252258

253-
@rx.var
254-
def welcome_message(self) -> str:
255-
return rx.cond(
256-
self.is_authenticated,
257-
f"Welcome, {self.username}!",
258-
"Please log in"
259-
)
260-
261-
def auth_example():
259+
class ContactFormState(ValidationMixin, rx.State):
260+
name: str = ""
261+
email: str = ""
262+
message: str = ""
263+
264+
@rx.event
265+
def submit_form(self):
266+
self.clear_errors()
267+
valid_name = self.validate_required("name", self.name)
268+
valid_email = self.validate_email(self.email)
269+
valid_message = self.validate_required("message", self.message)
270+
271+
if valid_name and valid_email and valid_message:
272+
self.is_loading = True
273+
yield rx.sleep(1)
274+
self.is_loading = False
275+
self.name = ""
276+
self.email = ""
277+
self.message = ""
278+
279+
def validation_example():
262280
return rx.vstack(
263-
rx.text(DashboardState.welcome_message),
281+
rx.heading("Contact Form"),
282+
rx.input(
283+
placeholder="Name",
284+
value=ContactFormState.name,
285+
on_change=ContactFormState.set_name,
286+
),
264287
rx.cond(
265-
DashboardState.is_authenticated,
266-
rx.button("Logout", on_click=DashboardState.logout),
267-
rx.hstack(
268-
rx.input(placeholder="Username", on_blur=DashboardState.login),
269-
rx.text("(Enter username to login)"),
270-
spacing="2",
271-
),
288+
ContactFormState.errors.contains("name"),
289+
rx.text(ContactFormState.errors["name"], color="red"),
290+
),
291+
rx.input(
292+
placeholder="Email",
293+
value=ContactFormState.email,
294+
on_change=ContactFormState.set_email,
295+
),
296+
rx.cond(
297+
ContactFormState.errors.contains("email"),
298+
rx.text(ContactFormState.errors["email"], color="red"),
299+
),
300+
rx.text_area(
301+
placeholder="Message",
302+
value=ContactFormState.message,
303+
on_change=ContactFormState.set_message,
304+
),
305+
rx.cond(
306+
ContactFormState.errors.contains("message"),
307+
rx.text(ContactFormState.errors["message"], color="red"),
308+
),
309+
rx.button(
310+
"Submit",
311+
on_click=ContactFormState.submit_form,
312+
loading=ContactFormState.is_loading,
272313
),
273314
spacing="4",
274315
align="center",
316+
width="300px",
275317
)
276318
```
277319

0 commit comments

Comments
 (0)