web
You’re offline. This is a read only version of the page.
close
Skip to main content
Community site session details

Community site session details

Session Id :
Power Apps - Building Power Apps
Suggested answer

Improve performance of 'like' button

(0) ShareShare
ReportReport
Posted on by 22
Hi all!
 
I'm hoping you can help me improve the performance of a 'like' button that I have added to a gallery. Essentially, the idea is that any user can 'like' items in the gallery.
 
I have a datasource SharePoint List of 'Ideas' and a separate SharePoint list of 'Likes' so I can keep track of total likes for each idea. Collections for the Ideas and Likes (and a separate collection of the user's own likes) are built when the screen is loaded and the gallery is fed by these Collections.
 
In practical terms:
- user clicks the 'like' icon (which is initially an empty heart image, not an icon)
- the button then changes to a full heart image
- the datasource table of 'Likes' is patched to add a record that is associated with that gallery record and with that particular user
- the gallery also shows a running total of Likes for each Idea
 
Three separate things are happening when the user clicks the Like button:
1. image source changes (toggles between empty heart and full heart image)
2. record is patched to Likes (or removed from Likes if that user has previously liked that Idea)
3. running total text label is updated
 
At the moment, this seems quite slow so this detracts from the user experience. There's a noticeable lag between clicking the 'Like' image and then seeing the image change and the running total get updated.
 
Here's the code I'm using for the OnSelect property of the 'like' image in the gallery:
If (
    CountRows(
        Filter(
            colUserLikes,
            Idea.Id = ThisItem.ID
        )
    ) = 0,
    Patch(
        Portal_Likes,
        Defaults(Portal_Likes),
        {
            Idea: {
                Id: ThisItem.ID,
                Value: ThisItem.ID
            },
            User: {
                Claims: "i:0#.f|membership|" & varUserEmail,
                Department: "",
                DisplayName: varUserName,
                Email: varUserEmail,
                JobTitle: " ",
                Picture: " "
            }
        }
    ),
    RemoveIf(
        Portal_Likes,
        Idea.Id = ThisItem.ID And User.DisplayName = varUserName
    )
);
Refresh(Portal_Likes);
ClearCollect(
    colLikes,
    Filter(
        'Portal_Likes',
        ManualID <> 0
    )
);
ClearCollect(
    colUserLikes,
    Filter(
        'colLikes',
        User.DisplayName = varUserName
    )
)
 
And here's the code I'm using for the Image property of the 'like' image in the gallery:
If (
    CountRows(
        Filter(
            colUserLikes,
            Idea.Id = ThisItem.ID
        )
    ) = 0,
    'empty_heart',
    'full_heart'
)
 
And here's the code I'm using in the Text property of the text label showing a running total:
If (
    CountRows(
        Filter(
            colLikes,
            Idea.Id = ThisItem.ID
        )
    ) = 1,
    CountRows(
        Filter(
            colLikes,
            Idea.Id = ThisItem.ID
        )
    ) & " like",
    CountRows(
        Filter(
            colLikes,
            Idea.Id = ThisItem.ID
        )
    ) & " likes"
)
 
 
 
Any help you can provide to optimise this code would be much appreciated! I expect I could do better with referencing variables or collections and reducing the calculations. Happy to use Named Formulas if this would provide a performance benefit for any aspect.
 
Thank you!
Categories:
I have the same question (0)
  • ronaldwalcott Profile Picture
    3,827 Super User 2025 Season 2 on at
    Improve performance of 'like' button
    One thing that you can do is refactor your code to run some aspects of it concurrently using the Concurrent function.
  • newbieappdeveloper Profile Picture
    22 on at
    Improve performance of 'like' button
    Thanks for your reply. I often use Concurrent when setting multiple variables but I don't see much opportunity to use it with the above code. I think it will need to be sequential (patch or remove, and then refresh datasource and then rebuild the colLikes collection and then rebuild the colUserLikes collection based on colLikes.
  • Suggested answer
    LessCodePaths Profile Picture
    100 on at
    Improve performance of 'like' button
    Hi,
     
    Why do you use collection?
    Why do you use refresh? It slows all the things down.
     
    Here's my recommendation
    1. Block
    With(
        {myLikeRecord: LookUp(Portal_Likes, Idea.Id=ThisItem.ID, User.DisplayName = varUserName)},
        If(
            IsBlank(myLikeRecord),
            Patch(
                Portal_Likes,
                Defaults(Portal_Likes),
                {
                    Idea: {
                        Id: ThisItem.ID,
                        Value: ThisItem.ID
                    },
                    User: {
                        Claims: "i:0#.f|membership|" & varUserEmail,
                        Department: "",
                        DisplayName: varUserName,
                        Email: varUserEmail,
                        JobTitle: " ",
                        Picture: " "
                    }
                }
            ),
            Remove(myLikeRecord)
        )
    )
     

    Here's a breakdown of each part:

    1. With(): Defines a temporary variable myLikeRecord that searches the Portal_Likes data source to see if there's already a "like" entry by the current user (varUserName) for the specific idea (ThisItem.ID).

    2. If(IsBlank(myLikeRecord)): Checks if myLikeRecord is blank, meaning the user has not yet liked this idea.

      • If true (user has not liked the idea):

        • Patch(): Adds a new "like" record to Portal_Likes with details about the idea (ThisItem.ID) and user (name, email, etc.), marking the idea as liked by this user.
      • If false (user has already liked the idea):

        • Remove(myLikeRecord): Removes the existing "like" record from Portal_Likes, effectively "unliking" the idea.
    2. Block
    If(
        IsBlank(LookUp(Portal_Likes, Idea.Id=ThisItem.ID, User.DisplayName = varUserName)),
        'empty_heart',
        'full_heart'
    )
    • LookUp(): Searches the Portal_Likes data source for a "like" entry where:

      • The idea's ID matches ThisItem.ID.
      • The user's display name matches varUserName.
    • IsBlank(): Checks if the lookup result is blank (i.e., if the user hasn't liked the idea).

    • If(): Returns:

      • 'empty_heart' if the user hasn't liked the idea, indicating an "unliked" state.
      • 'full_heart' if the user has liked the idea, indicating a "liked" state.
     
    3. Block
    With(
        {likesCount: CountRows(Filter(Portal_Likes, Idea.Id=ThisItem.ID))},
        $"{likesCount} {If(likesCount=1," like"," likes")}"
    )
    • With(): Defines a temporary variable, likesCount, which calculates the number of likes for the current idea (ThisItem.ID).

      • CountRows(Filter(...)): Filters the Portal_Likes data source to find all "like" records where Idea.Id matches ThisItem.ID, then counts those records.
    • $"{}": This syntax creates a formatted text string.

    • If(likesCount=1, " like", " likes"): Adds either "like" or "likes" based on the value of likesCount to ensure correct grammar.
       

    Could you try if it is better?
     
    L.
  • newbieappdeveloper Profile Picture
    22 on at
    Improve performance of 'like' button
    Thanks LessCodePaths.
     
    I follow your logic and that makes sense although your code for the first block is giving me two errors:
    1. The If function has some invalid arguments.
    2. The Remove function has an invalid number of arguments (received 1, expected 2 or more).
     
    I haven't been able to resolve these.
     
    The main reason for originally using Collections (with filters applied to the datasource SharePoint Lists) was to avoid delegation warnings. I'm trying to build the app from the ground up in a way that avoids problems with delegation in case the datasets grow over time. If I work with the SharePoint Lists directly then I'm getting delegation warnings (on using = with Idea.Id, and on using LookUp).
  • LessCodePaths Profile Picture
    100 on at
    Improve performance of 'like' button
    Hi, 
     
    you are right there was an issue in LookUp function.
    Here is revised version
    With(
        { 
            myLikeRecord: LookUp(Portal_Likes, Idea.Id = ThisItem.ID && User.DisplayName = varUserName) 
        },
        If(
            IsBlank(myLikeRecord),
            // If no like exists, create a new record
            Patch(
                Portal_Likes,
                Defaults(Portal_Likes),
                {
                    Idea: ThisItem,
                    User: {
                        Claims: "i:0#.f|membership|" & varUserEmail,
                        Department: "",
                        DisplayName: varUserName,
                        Email: varUserEmail,
                        JobTitle: " ",
                        Picture: " "
                    }
                }
            ),
            // If a like already exists, remove it
            Remove(Portal_Likes, myLikeRecord)
        )
    )
    
    When it comes to delegation, using of collections might help.
    However, I believe you can do it also without collections.
    Whats the statement defining colUserLikes?
     
    L.
  • newbieappdeveloper Profile Picture
    22 on at
    Improve performance of 'like' button
    Thank you.
     
    I've had to reinsert the Value property for Idea but the revised code when works.
     
    Here's how I'm building the colUserLikes collection when the app starts (and refreshing when needed):
     
    ClearCollect(colUserLikes, Filter(Portal_Likes, User.DisplayName = varUserName) );
  • Suggested answer
    LessCodePaths Profile Picture
    100 on at
    Improve performance of 'like' button
    Lets edit it a bit and it should work.
     
    Replace piece of code:
    LookUp(Portal_Likes, Idea.Id = ThisItem.ID && User.DisplayName = varUserName)
     
    With this code:
    First(Filter(Filter(Portal_Likes,User.DisplayName = varUserName),Idea.Id = ThisItem.ID))
    //Filter(Portal_Likes,User.DisplayName = varUserName) count must be smaller than delegation limit of your app (500 or 2000 based on app settings). But I would say it is
     
    Much better will be to change the property DisplayName to Email and varUserName to varUserEmail - it is more robust
    First(Filter(Filter(Portal_Likes,User.Email= varUserEmail),Idea.Id = ThisItem.ID))
     
    So at the end:
    1. Block
    With(
        {myLikeRecord: First(Filter(Filter(Portal_Likes,User.Email= varUserEmail),Idea.Id = ThisItem.ID))},
        If(
            IsBlank(myLikeRecord),
            Patch(
                Portal_Likes,
                Defaults(Portal_Likes),
                {
                    Idea: {
                        Id: ThisItem.ID,
                        Value: ThisItem.ID
                    },
                    User: {
                        Claims: "i:0#.f|membership|" & varUserEmail,
                        Department: "",
                        DisplayName: varUserName,
                        Email: varUserEmail,
                        JobTitle: " ",
                        Picture: " "
                    }
                }
            ),
            Remove(myLikeRecord)
        )
    )
    2. Block
    If(
        IsBlank(First(Filter(Filter(Portal_Likes,User.Email= varUserEmail),Idea.Id = ThisItem.ID))),
        'empty_heart',
        'full_heart'
    )
    3. Block
    With(
        {likesCount: CountRows(Filter(Portal_Likes, Idea.Id=ThisItem.ID))},
        $"{likesCount} {If(likesCount=1," like"," likes")}"
    )
    Let me know if it is better.
     
    L.
  • jamezm79 Profile Picture
    18 on at
    Improve performance of 'like' button
    Thanks LessCodePaths. Definitely an improvement. FYI, I had to fix the Remove code again but that was straightforward.
     
    So that just leaves the delegation warnings for the "Idea.Id = ThisItem.ID" part of the filter. Should I just learn to live with this?
  • LessCodePaths Profile Picture
    100 on at
    Improve performance of 'like' button
    Unfortunately, LookUp for Id is not delegable.
    However, if you use it like this:
    Filter(Filter(Portal_Likes,User.Email= varUserEmail),Idea.Id = ThisItem.ID))
    …and the first filter returns fewer than 2000 items, it will work since the outer filter is processed in the browser.
     
    If you want to avoid delegation warnings, you can use Idea.Value = ThisItem.UniqueNamewhich is surprisingly delegable!
    Just ensure that the UniqueName column has unique values across the list (for example, generated programmatically as "Idea 1," "Idea 2," etc.).

    For large datasets, I recommend avoiding the use of LookUp columns for relationships.

    L.
     

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Chiara Carbone – Community Spotlight

We are honored to recognize Chiara Carbone as our Community Spotlight for November…

Leaderboard > Power Apps

#1
WarrenBelz Profile Picture

WarrenBelz 632 Most Valuable Professional

#2
Michael E. Gernaey Profile Picture

Michael E. Gernaey 386 Super User 2025 Season 2

#3
wolenberg_ Profile Picture

wolenberg_ 245 Moderator

Last 30 days Overall leaderboard