Asynchronous action error

Hello ! I have a problem with 2 action call being made at the same time, to summarize I have 2 TextFields that when "FocusChanged" call a custom action that change data in a DB with the content of the textfields.

PS : The error occurs because the 2 action call change the same List inside my DB

Current Behavior

Everything works fine when I just "FocusChange" by clicking anywhere on my app after entering my data in my TextField, but the problem comes when I click on another TextField. (See video)

What's happening is that my action is called a first time by the "FocusChange" of the first TextField and so it change the data in my DB fine, but since I've clicked on another TextField my action is called a second time but it doesn't wait for the first call to be finished and therefore :

  • First action is called and get the List inside my DB

  • Second action is called and get the List inside my DB

  • First action change the data inside my DB

  • Second action overwrite the data inside my DB with the old data

You can see that happening here, the second call gets its data before the first one write his, and so the second call gets outdated data.

Expected Behavior

  • First action is called and get the List inside my DB

  • First action change the data inside my DB

  • Second action is called and get the List inside my DB

  • Second action change the data inside my DB

or

  • First action is called and get the List inside my DB

  • First action change the data inside my DB

  • Second action isn't called (The "onFocusChange" action is only triggered when the focus is lost)

Steps to Reproduce

  • Create a page

  • Add 2 or more TextFields

  • Create a DB with a List inside

  • Add a custom action on the TextFields "onFocusChange" trigger to change List[ i ] in the DB

  • Enter some data in the first TextField and then select the other TextField without unselecting the first one

  • Your data will not be saved to your Firebase DB (it will have been overwritten)

Enregistrement de l’écran 2023-12-05 à 16.46.53 (1) (1).mov
7.31MB

Version

- FlutterFlow version: FlutterFlow v4.0 released December 1, 2023, Flutter version 3.13.7
- Platform: Web
- Browser name and version: Chrome 119.0.6045.199 (Build officiel) (arm64)
- Operating system and version affected: MacOS 14.1.1(23B81) and Windows10

Custom Action

// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/actions/index.dart'; // Imports other custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom action code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'package:cloud_firestore/cloud_firestore.dart';

// In the user collection, if it does not exist create the cat1 list with 50 empty elements

Future<String> updateList(
  String? data,
  int? pos,
  String? documentRef,
  String? catName,
) async {
  // null check
  data ??= 'error';
  pos ??= 0;
  documentRef ??= '';
  catName ??= '';
  debugPrint("Data : ");
  debugPrint(data);
  // Get the user document reference
  DocumentReference userRef =
      await FirebaseFirestore.instance.collection('users').doc(documentRef);
  DocumentSnapshot userSnapshot = await userRef.get();

  // Check if the user document exists
  if (userSnapshot.exists) {
    // If the user document exist, get the list or create it
    Map<String, dynamic> dataMap = userSnapshot.data() as Map<String, dynamic>;
    List<dynamic> catList = List.filled(100, '');
    if (!dataMap.containsKey(catName)) {
      await userRef.update({catName: catList});
    } else {
      catList = userSnapshot.get(catName);
    }
    catList[pos] = data;
    debugPrint(catList.join(' '));
    await userRef.update({catName: catList});
    return ("OK");
  } else {
    // If the user document does not exists return an error
    return ("KO");
  }
}
3 replies