2
\$\begingroup\$

I have the function which updates user data (currently only name). I would like to optimize its logic and particularly logic of updating participant name in chats. Currently I get entire chats collection where I find objects where the participants array contains the current user name (who wants to update their profile) and change its previous name with a new desired name. After that I update the entire chats collection with new data (i.e updatedChats). I need to make it work faster if possible and improve code quality.

Chats collection:

Chats collection

Function code:

 async updateUser(data: IUser) {
    const user = auth.currentUser;
    if (!user) return;
    
    // Updating user name in chats -> chat object -> participants  
    const q = query(collection(db, "chats"));
    const querySnapshot = await getDocs(q);
    const chats = querySnapshot.docs.map((doc) => doc.data() as IChat);

    const updatedChats = chats.map((chat) => {
      if (user.displayName && chat.participants.includes(user.displayName)) {
        if (user.displayName === chat.participants[0]) {
          return {
            ...chat,
            participants: [data.name, chat.participants[1]],
          };
        } else {
          return {
            ...chat,
            participants: [chat.participants[0], data.name],
          };
        }
      }
      return chat;
    });

    await Promise.all(
      updatedChats.map(async (chat) => {
        const chatDocRef = doc(db, "chats", chat.chatId);
        await updateDoc(chatDocRef, { participants: chat.participants });
      })
    );
    
    // other logic
    const userDocRef = doc(db, "users", user.uid);
    await updateDoc(userDocRef, {
      name: data.name,
      bio: data.bio,
    });

    if (auth.currentUser) {
      await updateProfile(auth.currentUser, {
        displayName: data.name,
      });
    }
  }
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Data to load can likely be reduced

Instead of loading the entire collection of chats one could load only chats with the participants containing the username - likely using the array-contains operator with the where() method.

Condition to ensure name is set can likely be moved

Also, the second line of the updateUser() method is:

if (!user) return;

while the condition inside the first callback to the map() method is this:

if (user.displayName && chat.participants.includes(user.displayName)) {

The second line of the method could be updated to also ensure the displayName is set and not empty - perhaps checking with a logical AND operator:

if (!(user && user.displayName)) return;

Or using the optional chaining operator ?.:

if (!user?.displayName) return;

Data to update can be simplified

The callback to the map() method returns an updated chat if the displayName is found:

    if (user.displayName === chat.participants[0]) {
      return {
        ...chat,
        participants: [data.name, chat.participants[1]],
      };
    } else {
      return {
        ...chat,
        participants: [chat.participants[0], data.name],
      };
    }

The only line in that block that is different is the participants. One could declare that as a variable which is assigned with the help of a ternary operator. This allows for a single return statement.

    const participants = (user.displayName === chat.participants[0])
      ? participants: [data.name, chat.participants[1]]
      : [chat.participants[0], data.name];
    return {
      ...chat,
      participants
    };
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.