Skip to main content

State Management

The app uses the Provider pattern for state management.

Providers

AuthProvider

Manages user authentication state.

State:

  • phoneNumber - User's phone number
  • isVerified - Authentication status
  • userRole - Current user role (PROVIDER/SERVICE_SEEKER)
  • userData - User profile data
  • isLoading - Loading state
  • errorMessage - Error messages

Methods:

  • sendOTP(phone, role) - Request OTP
  • verifyOTP(code) - Verify OTP code
  • signOut() - Sign out user
  • initialize() - Load saved session

LocationProvider

Manages location services and tracking.

JobProvider (if exists)

Manages job-related state.

Usage Patterns

Reading State

// Using Consumer (rebuilds on changes)
Consumer<AuthProvider>(
builder: (context, authProvider, child) {
return Text(authProvider.phoneNumber ?? 'Not logged in');
},
)

// Using Provider.of (one-time read)
final authProvider = Provider.of<AuthProvider>(context, listen: false);
final phone = authProvider.phoneNumber;

Updating State

final authProvider = Provider.of<AuthProvider>(context, listen: false);
authProvider.setPhoneNumber('+264812345678');

Listening to State Changes

// Consumer automatically rebuilds when state changes
Consumer<AuthProvider>(
builder: (context, authProvider, child) {
if (authProvider.isLoading) {
return CircularProgressIndicator();
}
return YourWidget();
},
)

Best Practices

  1. Use listen: false when you only need to call methods, not read state
  2. Use Consumer when UI needs to react to state changes
  3. Minimize provider scope - only wrap widgets that need the provider
  4. Separate providers for different concerns
  5. Handle loading and error states in providers

Local State vs Global State

  • Global State (Provider): User authentication, app settings, shared data
  • Local State (setState): UI-only state like form inputs, animations