Search code examples
flutterdartwidgetflutter-dependencies

Map got edited in a function without any return statement


So strange behavior for me, I am so confused, I have been with these 3 hours and still don't get it.

Problem :

I am calling an instance from a provider withe name “idea” and later using that instance attribute in my widget.

This is my instance :

Widget build(BuildContext context) {
    var idea = Provider.of<Idea>(context, listen: false).allideas.firstWhere(
          (element) => element.id == widget.idea_id,
        );

then I am calling another provider to call two functions

  • HTTP request

            final connectionData =
                await Provider.of<IdeaConnection>(context, listen: false)
                    .createIdeaConnection(
              idea.userId,
              idea.id,
            );
                final ideaProvider =
                    Provider.of<IdeaConnection>(context, listen: false);
                await ideaProvider.uppdeaIdeaConnectionsprov(
                  idea.connections,
                  connectionData,
                );
    
    Future<dynamic> createIdeaConnection(int resiver_user_id, int idea_id) async {
        final url = Uri.parse('http://10.0.2.2:3000/ideaconnetion');
        var jwt = await storage.read(key: "token");
        var userid = await storage.read(key: "id");
        var response;
        if (jwt != null) {
          final Map<String, String> tokenData = {
            "Content-Type": "application/json",
            "token": jwt
          };
          try {
            response = await http.post(url,
                headers: tokenData,
                body: json.encode({
                  "resiver_user_id": resiver_user_id,
                  "idea_id": idea_id,
                }));
            response = jsonDecode(response.body);
          } catch (error) {
            print(error);
            rethrow;
          }
        }
        return response;
      }
    
  • calling another function to update data locally

    Future<void> uppdeaIdeaConnectionsprov(
        Map<int, IdeaConnectionsModel> connections, data) async {
      var id = await storage.read(key: "id") as String;
      var userData = await getLogedinUserData();
      connections.putIfAbsent(
          data['user_id'],
          () => IdeaConnectionsModel(
                id: data['id'],
                uppdatedAtt: DateTime.parse(data['updatedAt']),
                fName: userData['fName'] as String,
                imge: stringToByteList(userData['image']!),
                lNmae: userData['lName'] as String,
                userId: int.parse(id),
                userName: userData['userName'] as String,
                accepted: false,
                idea_Id: data['idea_id'],
              ));
    }
    

What is strange is that the uppdeaIdeaConnectionsprov() do not return any map, but the map I am sending to the function gets updated and i see changes in my Text widget how is this possible......

> Text(
>                             "${idea.connections.length}  Connections",
>                             style: const TextStyle(
>                                 color: Colors.white,
>                                 fontWeight: FontWeight.bold,
>                                 fontSize: 12),
>                           ),

Solution

  • As stated in the documentation, putIfAbsent() modifies the current map. If you want the current map to remain unchanged and get a new map with new values, you can clone the existing map and call putIfAbsent() on the new map.

    Future<Map<int, IdeaConnectionsModel>> uppdeaIdeaConnectionsprov(
        Map<int, IdeaConnectionsModel> connections, data) async {
      var id = await storage.read(key: "id") as String;
      var userData = await getLogedinUserData();
      
      return Map<int, IdeaConnectionsModel>.from(connections)..putIfAbsent(
          data['user_id'],
              () => IdeaConnectionsModel(
            id: data['id'],
            uppdatedAtt: DateTime.parse(data['updatedAt']),
            fName: userData['fName'] as String,
            imge: stringToByteList(userData['image']!),
            lNmae: userData['lName'] as String,
            userId: int.parse(id),
            userName: userData['userName'] as String,
            accepted: false,
            idea_Id: data['idea_id'],
          ));
    }