Search code examples
blazorblazor-server-sideblazor-webassembly

Cannot re-render Blazor components that are generated by foreach


I have a componet that contains a list of posts. I want to delete some posts. my problem is that the removed posts does not removed on the screen, even when I use StateHasChanged().

Here is PostListComponent.razor file

@if (PostsList != null)
{
    foreach (var post in PostsList)
    {
        if(post.IsDeleted != true)
        {
         <div>
          <span @onclick="@(()=>DeletePost(post.PostId))" class="oi oi-trash" style="cursor: pointer;"></span>
          <p>post.Content</p>
         </div>
        }
     }
}

and PostListComponent.cs :

public partial class PostListComponent : ComponentBase
{

 [Parameter]
 public List<PostContent> PostsList { get; set; }    

 protected void DeletePost(string postId)
 {
    PostsList.FirstOrDefault(p => p.PostId == postId).IsDeleted=true;
    InvokeAsync(StateHasChanged);
 }

 protected override async Task OnInitializedAsync()
 {
    DBContext _db;
    _db = DbFactory.CreateDbContext();
    PostsList = _db.Posts.Where(s => (s.IsDeleted != true).ToList();

  }
}

Solution

  • According to [1], using the @key directive is required for rendering a list of elements or components and the elements or components subsequently change.

    Using @key directive solve the problem.

    Here is the code:

    @if (PostsList != null)
    {
        foreach (var post in PostsList)
        {
            if(post.IsDeleted != true)
            {
             <div @key="post">
              <span @onclick="@(()=>DeletePost(post.PostId))" class="oi oi-trash" style="cursor: pointer;"></span>
              <p>post.Content</p>
             </div>
            }
         }
    }
    

    I would like to appreciate Brian Parker for his comment on this problem.