GrandMagus
GrandMagus

Reputation: 742

Not updating state with provider after patch/update, Flutter

It seems my UI is not updating the changes after I have patched the info over the API. I'm using Provider for state management. Here is the code:

UPDATE: Changed the data to be an object as send it as one to the API endpoint

UserModel :

class UserData{
  String name,
      surname,
      birthDate;

  UserData({
    this.generalEmail,
    this.surname,
    this.primaryPhone,
  });

  UserData.fromJson(Map<String, dynamic> json) {
    name= json['name'];
    surname = json['surname'];
    birthDate= json['birthDate'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = Map<String, dynamic>();
    data['name'] = this.name;
    data['surname'] = this.surname;
    data['birthDate'] = this.birthDate;

    return data;
  }
}


User Store:

class UserStore extends ChangeNotifier {

  Map<String, UserData> _userInfo = {};
  Map<String, UserData> get userInfo => _userInfo ;

 void updateUserInfo(UserData user) {
    _userInfo[user.userId] = user;
    notifyListeners();
  }

UserData  getUserInfoByUserId(String userId) => _userInfo[userId];
}

And the service action for the User Store:


  UserStore userStore;

  BuildContext context;

  UserActions(BuildContext context) {
    this.context = context;
    this.userStore = Provider.of<UserStore>(context, listen: false);
  }

Future<HTTPResponse<UserData>> patchUserInfo(UserData user) async {
    final response = await ApiRequest(Method.PATCH, '/users',
        body: jsonEncode(user.toJson()));
    dynamic body = jsonDecode(response.body);
    if (response.statusCode == 200) {
      dynamic data = body['data'];
      UserData user = UserData();
      if (data != null) {
        user = UserData.fromJson(data);
      }
      return HTTPResponse<UserData>(
        isSuccessful: true,
        data: user,
        message: HTTPResponse.successMessage,
        statusCode: response.statusCode,
      );
    } else {
      return HTTPResponse<UserData>(
        isSuccessful: false,
        data: null,
        message: body['message'] ?? HTTPResponse.errorMessage,
        statusCode: response.statusCode,
      );
    }
  }

 Future<void> changeUserInfo(UserData user) async {
    final userRes = await patchUserInfo( // call the API and pass the data
        user);
    if (userRes != null) {
      userStore.updateUserInfo(user);
      return;
    }
    userStore.updateUserInfo(user);
  }

UI that is not updating:

final userStore = Provider.of<UserStore>(context, listen: false);
    UserData user = userStore.getUserInfo(userId);
...
return Column(
children: [
    Text(user.name), // only updates it when I refresh the widget
    Text(user.surname), // only updates it when I refresh the widget
    Text(user.birthDate), // only updates it when I refresh the widget
   ],
);

After the API goes through, I want to update my UI with the latest changes if not, don't update the UI. I'm not sure, but it's probably the updateUserInfo method inside the UserStore that I'm not setting right in order to update the UI immediately after the successful API call. Where is my mistake? I can use indexWhere when it's a list, but how do I update it then when the data model is a Map like I defined it in the UserStore?

Thanks in advance for you help!

Upvotes: 0

Views: 273

Answers (1)

Peter Koltai
Peter Koltai

Reputation: 9734

You are not listening to the changes in your Provider (see: listen: false). You can use the following code to get notified upon changes you make with updateUserInfo:

return Consumer<UserStore>(builder: (context, UserStore userStore, child) {
  UserData user = userStore.getUserInfo(userId);
  return Column(
    children: [
      Text(user.name),
      Text(user.surname), 
      Text(user.birthDate),
    ],
  );
});

And use this when you get data from API (since here you don't need to listen):

context.read<UserStore>().updateUserInfo(userRes);

Create a provider like this, above the Consumer:

return ChangeNotifierProvider(create: (context) => UserStore(), child: ...);

Upvotes: 1

Related Questions