Flutter Realm: User.Customdata is always null

Hi @Salman_lartey,

As @Desislava_St_Stefanova mentioned, the custom user data is stored in the JWT, so it can be stale if you update the custom user data after logging in and before the next refresh of the access token. Note this section of the docs:

App Services does not dynamically update the value of the User.customData immediately when underlying data changes

How are you creating the custom user data documents? If it’s after login, consider adding a call to user.refreshCustomData() before trying to access it.

Hi @Kiro_Morkos ,

I do it as follows,

  Future<userModel.User> logInWithGoogle() async {
    final result = await login();
    final ggAuth = await result!.authentication;

    final credentials = Credentials.jwt(ggAuth.idToken!);
    final user = await _app.logIn(credentials);

    await user.refreshCustomData(); // Refresh the custom data
    final AuthLink authLink = AuthLink(
      getToken: () async {
        return 'Bearer ${ggAuth.idToken!}';
      },
    );

    final Link link = authLink.concat(ApiConstants.httpLink);

    final GraphQLClient client = GraphQLClient(
      link: link,
      cache: GraphQLCache(),
    );

    final MutationOptions options = MutationOptions(
      document: gql('''
    mutation Login(\$displayName: String!, \$email: String!, \$photoUrl: String!, \$userId: String!, \$isActive: Boolean!) {
      login(displayName: \$displayName, email: \$email, photoUrl: \$photoUrl, userId: \$userId, isActive: \$isActive) {
        userId
        email
        displayName
        photoUrl
        isActive
      }
    }
  '''),
      variables: <String, dynamic>{
        'displayName': user.profile.name ?? 'Unknown',
        'email': user.profile.email!,
        'photoUrl': user.profile.pictureUrl!,
        'userId': user.id,
        'isActive': true
      },
    );

    final QueryResult result2 = await client.mutate(options);

    if (result2.hasException) {
      throw Exception('Error logging in: ${result2.exception}');
    }

    final data = result2.data!['login'];

    user2 = userModel.User.fromJson(data);

    // Save the user's authentication credentials in the device's secure storage
    final storage = FlutterSecureStorage();
    await storage.write(key: 'jwtToken', value: ggAuth.idToken!);
    // await storage.write(key: 'lives', value: user2.lives);
    _token = _app.currentUser!.accessToken;
    // _token = ggAuth.idToken!;
    // _exprireDate = DateTime.now().add(Duration: (seconds))!;

    final customUserData = user.customData; // Access the custom data
    user.refreshCustomData();
    logger.d(customUserData);
    notifyListeners();
    return user2;
  }

And even when i add it in i still get Null:

 @override
  void initState() {
    super.initState();

    final realmService = Provider.of<RealmService>(context, listen: false);
    final user = realmService.currentUser;

    user!.refreshCustomData();
    socketClient.emit('setUser', user.profile.email);

    try {
      setState(() {
        final customUserData = user.customData;
        customUserData!.refreshCustomData();
        logger.d(customUserData);
      });
    } catch (e) {}

Can you await each call to refreshCustomData to ensure the future is resolved before try to access the custom user data?

@Kiro_Morkos ,I have set it as follow:

Future<userModel.User> logInWithGoogle() async {
    final result = await login();
    final ggAuth = await result!.authentication;

    final credentials = Credentials.jwt(ggAuth.idToken!);
    final user = await _app.logIn(credentials);

    await user.refreshCustomData(); // Refresh the custom data
    final AuthLink authLink = AuthLink(
      getToken: () async {
        return 'Bearer ${ggAuth.idToken!}';
      },
    );

    final Link link = authLink.concat(ApiConstants.httpLink);

    final GraphQLClient client = GraphQLClient(
      link: link,
      cache: GraphQLCache(),
    );

    final MutationOptions options = MutationOptions(
      document: gql('''
    mutation Login(\$displayName: String!, \$email: String!, \$photoUrl: String!, \$userId: String!, \$isActive: Boolean!) {
      login(displayName: \$displayName, email: \$email, photoUrl: \$photoUrl, userId: \$userId, isActive: \$isActive) {
        userId
        email
        displayName
        photoUrl
        isActive
      }
    }
  '''),
      variables: <String, dynamic>{
        'displayName': user.profile.name ?? 'Unknown',
        'email': user.profile.email!,
        'photoUrl': user.profile.pictureUrl!,
        'userId': user.id,
        'isActive': true
      },
    );

    final QueryResult result2 = await client.mutate(options);

    if (result2.hasException) {
      throw Exception('Error logging in: ${result2.exception}');
    }

    final data = result2.data!['login'];

    user2 = userModel.User.fromJson(data);

    final storage = FlutterSecureStorage();
    await storage.write(key: 'jwtToken', value: ggAuth.idToken!);
    _token = _app.currentUser!.accessToken;

    final customUserData = user.customData; // Access the custom data
    await user.refreshCustomData(); // Refresh the custom data
    logger.d(customUserData);
    notifyListeners();
    return user2;
  }

And it is still showing null, idk what im doing wrong:

Okay, I managed to fix it by doing the following code:

  Future<userModel.User> logInWithGoogle() async {
    final result = await login();
    final ggAuth = await result!.authentication;

    final credentials = Credentials.jwt(ggAuth.idToken!);
    final user = await _app.logIn(credentials);

    currentUser = user;

    final AuthLink authLink = AuthLink(
      getToken: () async {
        return 'Bearer ${ggAuth.idToken!}';
      },
    );

    final Link link = authLink.concat(ApiConstants.httpLink);

    final GraphQLClient client = GraphQLClient(
      link: link,
      cache: GraphQLCache(),
    );

    final MutationOptions options = MutationOptions(
      document: gql('''
    mutation Login(\$displayName: String!, \$email: String!, \$photoUrl: String!, \$userId: String!, \$isActive: Boolean!) {
      login(displayName: \$displayName, email: \$email, photoUrl: \$photoUrl, userId: \$userId, isActive: \$isActive) {
        userId
        email
        displayName
        photoUrl
        isActive
      }
    }
  '''),
      variables: <String, dynamic>{
        'displayName': user.profile.name ?? 'Unknown',
        'email': user.profile.email!,
        'photoUrl': user.profile.pictureUrl!,
        'userId': user.id,
        'isActive': true
      },
    );

    final QueryResult result2 = await client.mutate(options);

    if (result2.hasException) {
      throw Exception('Error logging in: ${result2.exception}');
    }
    await currentUser!.refreshCustomData(); // Refresh the custom data
    logger.d(currentUser!.customData);
    final data = result2.data!['login'];

    user2 = userModel.User.fromJson(data);

    final storage = FlutterSecureStorage();
    await storage.write(key: 'jwtToken', value: ggAuth.idToken!);
    _token = _app.currentUser!.accessToken;

    final customUserData = user.customData; // Access the custom data
    await currentUser!.refreshCustomData(); // Refresh the custom data

    logger.d(customUserData);
    notifyListeners();
    return user2;
  }

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.