0

My goal: Retrieve data from firestore and display said data once.

Problem: Same data is retrieving multiple times. If there is 5 rows of data, the array of my model retrieves 5 times. Why is this happening?

Here is my firestore model:

"Users - Investors"
   "currentUser.uid"
      "id": currentUser
      "fullName": fullName,
      "username": username,
      "userLocation": userLocation,
      "birthday": birthday

Here is my model:

struct InvestorModel: Identifiable {
    let id: String
    let fullName: String
    let username: String
    let userLocation: String
    let birthday: Date
}

Here is my vm:

class InvestorProfileViewModel: ObservableObject {
    @Published var investorProfile: [InvestorModel] = []
    
    private var auth = Auth.auth()
    private var store = Firestore.firestore()
    
    func getUserInfo() {
        let currentUser = auth.currentUser?.uid ?? ""
        store.collection("Users - Investors").document(currentUser).addSnapshotListener { snapshot, error in
            guard let data = snapshot?.data(), error == nil else {
                print("NO INVESTOR DATA, TRYING ARTIST DATA")
                return
            }

            DispatchQueue.main.async {
                self.investorProfile = data.map { (dataSnapshot) -> InvestorModel in
                    return InvestorModel(
                        id: currentUser,
                        fullName: data["fullName"] as? String ?? "",
                        username: data["username"] as? String ?? "",
                        userLocation: data["userLocation"] as? String ?? "",
                        birthday: data["birthday"] as? Date ?? Date()
                    )
                }
                print(self.investorProfile)
            }
        }
    }
}

Here is my view:

struct HomeView: View {
    @EnvironmentObject var hvm: HomeViewModel
    @EnvironmentObject var ipvm: InvestorProfileViewModel
    @Environment(\.colorScheme) var colorScheme
    
    let devInvestor = DeveloperPreview.instance.investor
    
    var body: some View {
        ZStack {
            Color.theme.background.ignoresSafeArea(.all)
            VStack {
                ForEach(ipvm.investorProfile) { investor in
                    MenuContent(investor: investor, menuWidth: menuWidth)
                }
            }
            .padding(.vertical, 20)
            .padding(.horizontal, 30)
        }
        .onAppear {
            self.ipvm.getUserInfo()
        }
    }
}

The print call inside of getUserInfo() returns:

[musifi.InvestorModel(id: "F65D7CB4-25B3-47C5-9A26-78C645916AAC", fullName: "John Doe", username: "johnn", userLocation: "Lake Elsinore, CA, USA", birthday: 2021-10-15 00:59:47 +0000),

[musifi.InvestorModel(id: "F65D7CB4-25B3-47C5-9A26-78C645916AAC", fullName: "John Doe", username: "johnn", userLocation: "Lake Elsinore, CA, USA", birthday: 2021-10-15 00:59:47 +0000),

musifi.InvestorModel(id: "2B4AE47A-4C55-4229-AB9F-1F2BA9983B44", fullName: "John Doe", username: "johnn", userLocation: "Lake Elsinore, CA, USA", birthday: 2021-10-15 00:59:47 +0000),

musifi.InvestorModel(id: "E8F87591-DC12-4068-958E-D2DA9025C316", fullName: "John Doe", username: "johnn", userLocation: "Lake Elsinore, CA, USA", birthday: 2021-10-15 00:59:47 +0000),

musifi.InvestorModel(id: "95C8B099-C753-410E-AF7D-72EDD8FB0E7D", fullName: "John Doe", username: "johnn", userLocation: "Lake Elsinore, CA, USA", birthday: 2021-10-15 00:59:47 +0000)]

4 types of data: fullName, username, userLocation, birthday - and 4 times it was called. This number always correlates. I am only calling the function once.

Trevor
  • 580
  • 5
  • 16
  • Try `@ObservedtObject var ipvm: InvestorProfileViewModel` – Rob C Oct 15 '21 at 01:32
  • @Rob Didnt work for me, it has to be something to do with .map - not referencing the vm – Trevor Oct 15 '21 at 01:58
  • Another thing you may wanna try is `investorProfile.append(contentsOf: YOUR MAP RESULTS)` – Rob C Oct 15 '21 at 02:59
  • @Rob still no luck, Im extremely puzzled at this point. – Trevor Oct 15 '21 at 05:17
  • @Rob you were onto something with .append() but it appears .map was the problem which is why it did not work to do your suggestion, thanks for pointing me in the right direction! – Trevor Oct 15 '21 at 06:42
  • What happens when you move the call `getUserInfo()` from `.onAppear` into the initializer of the view itself? That should fix your problem. – trndjc Oct 15 '21 at 21:08
  • @liquid I tried that, did not work. It had to of been related to .map, it was the only thing that solved my problem when removing it. Ill mark my own answer correct when i can – Trevor Oct 15 '21 at 23:43

1 Answers1

0

Im still not entirely sure why this works, but it does. Its possible that .map was iterating for every single row. - Please comment any theories so I can better understand, thanks!

    func getInvestorProfile() {
        store.collection("Users - Investors").document(auth.currentUser?.uid ?? "").addSnapshotListener { snapshot, error in
            guard let data = snapshot?.data(), error == nil else {
                print("NO INVESTOR DATA, TRYING ARTIST DATA")
                return
            }

            DispatchQueue.main.async {
                self.investorProfile.append(
                    InvestorModel(id: data["id"] as? String ?? "",
                                  fullName: data["fullName"] as? String ?? "",
                                  username: data["username"] as? String ?? "",
                                  userLocation: data["userLocation"] as? String ?? "",
                                  birthday: data["birthday"] as? Date ?? Date()
                                 )
                )
                print(self.investorProfile)
            }
        }
    }
Trevor
  • 580
  • 5
  • 16