skip to Main Content

I have a state with multiple variables

im changing the state with setters state but every time i change the state with setter state variables reset to initial state

here is my state

const AuthSignInState({
 this.signUpType = 'email',
 this.errorMessage = '',
 this.errorSignIn = false,
 this.isLoading = false,
 this.currentUser = '',
 this.user,
});

final String errorMessage;
final bool errorSignIn;
final String signUpType;
final bool isLoading;
final String currentUser;
final Sync? user;
}

here is my setter state for example i want to change the signuptype when i trigger this state other variables will reset to the initial value how can i persist the state even after setting one variable

class SetSignInTypeState extends AuthSignInState {
  final String type;
  const SetSignInTypeState({required this.type}) : super(signUpType: type);

  @override
  List<Object?> get props => [type];
}

2

Answers


  1. It is because the setter state is creating a new instance of the state class with the updated values. This means that the old instance of the state class is discarded and all of its values are lost.

    You can use ChangeNotifier or StreamController to persist the state even after setting one variable.

    1. By ChangeNotifier

      class AuthSignInState extends ChangeNotifier {
        const AuthSignInState({
            this.signUpType = 'email',
            this.errorMessage = '',
            this.errorSignIn = false,
            this.isLoading = false,
            this.currentUser = '',
            this.user,
        });
      
        final String errorMessage;
        final bool errorSignIn;
        final String signUpType;
        final bool isLoading;
        final String currentUser;
        final Sync? user;
      
        void setSignUpType(String type) {
            this.signUpType = type;
            notifyListeners();
        }
      }
      

    In this code, the setSignUpType() method sets the signUpType variable and then calls the notifyListeners() method to notify its listeners that the state has changed. This ensures that the UI will be updated to reflect the new value of the signUpType variable.

    1. By StreamController

      class AuthSignInState {
           final String errorMessage;
           final bool errorSignIn;
           final String signUpType;
           final bool isLoading;
           final String currentUser;
           final Sync? user;
      
           final StreamController<AuthSignInState> _controller =
                 StreamController<AuthSignInState>();
      
           AuthSignInState({
             this.signUpType = 'email',
             this.errorMessage = '',
             this.errorSignIn = false,
             this.isLoading = false,
             this.currentUser = '',
             this.user,
      });
      
          Stream<AuthSignInState> get stream => _controller.stream;
      
          void setSignUpType(String type) {
             this.signUpType = type;
             _controller.sink.add(this);
         } 
      }
      

    In the above code, the setSignUpType() method sets the signUpType variable and then adds a new event to the _controller stream. This event will be emitted to all of the listeners of the stream, which will then update their UI accordingly.

    Let me know if this helps.

    Login or Signup to reply.
  2. To preserve all values and change only one (or few) of them, it’s common to use methods like copyWith. Then you create a new instance of an object with all the values of the old one, with changes specified in arguments of that function. It is made very easy with freezed package (https://pub.dev/packages/freezed). Checkout it on pub.dev and also here is Flutter’s team short explanation of this package’s capabilities https://youtu.be/RaThk0fiphA

    In general the implementation looks like this:

    @freezed
    class AuthSignInState with _$AuthSignInState {
      const factory AuthSignInState({
        final String errorMessage,
         required bool errorSignIn,
         required String signUpType,
         required bool isLoading,
         required String currentUser,
         required Sync? user,
      }) = _AuthSignInState;
    }
    

    Then, after generating your code with build_runner, you would have in your bloc:

    emit(state.copyWith(signUpType: newSignUpType));
    

    Freezed is an efficient and less time consuming solution to change properties of an object. Hope that helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search