【问题标题】:Parameter / CascadingParameter not updating object参数/CascadingParameter 不更新对象
【发布时间】:2020-07-28 11:26:22
【问题描述】:

我想通过EventCallback 更新子组件TodoComponent 中的TodoItem

在我的TodoPage.razor.cs 中,我实现了一个更新方法:

public async void UpdateTodo(TodoItem todoItem)
{
    await Http.PutAsJsonAsync("todo", todoItem);
    await RefreshTodos();
}

然后我试图传递给负责渲染对象的TodoComponent

@foreach (var item in @TodoItems)
{
    <div class="row">
            <CascadingValue Value=@item Name="TodoItem">
                <TodoComponent UpdateCallback="@(async () => UpdateTodo(item))">
                </TodoComponent>
            </CascadingValue>
    </div>
}

TodoComponent.razor

@inherits ListOfTodos.Client.Components.TodoComponentBase
<div class="input-group col-12">
    <div class="input-group-prepend">
        <div class="input-group-text">
            <input type="checkbox" @bind="@TodoItem.IsDone" onclick="@UpdateCallback">
        </div>
    </div>

    <div class="col-8">
        <input type="text" class="form-control" @bind="@TodoItem.TaskName" oninput="@UpdateCallback" />
    </div>

    <div class="input-group-append">
        <input type="date" @bind="@TodoItem.DueDate" />
    </div>
</div>

附加信息:

public async Task RefreshTodos()
{
    TodoItems = await Http.GetFromJsonAsync<List<TodoItem>>("todo");
    StateHasChanged();
}
public class TodoComponentBase : ComponentBase
{
    [CascadingParameter(Name = "TodoItem")]
    public TodoItem TodoItem { get; set; }

    [Parameter]
    public EventCallback<TodoItem> UpdateCallback { get; set; }

    protected override Task OnInitializedAsync()
    {
        return base.OnInitializedAsync();
    }

}

当我调用UpdateCallback 虽然onchangeoninputTodoItem 就像它根本没有更新一样,我不知道绑定是否按我的预期工作去做。

如何正确地将对象传递给子组件并使其正确更新?

这是 github 仓库:https://github.com/DgoNeves/Blazor.ListOfTodos 它在内存中工作,因此您不需要任何数据库来运行它。

编辑:我不完全知道为什么会发生这种情况,但显然控制器调用是出于某种原因。

【问题讨论】:

  • 致电StateHasChanged()
  • 我添加了一些附加信息以表明我已经在调用 stateHasChanged,尽管它与 UI 无关,因为当我在 UI 中进行更改时,问题是对象没有更新,因此在调用 API 时它被“更新”到相同的状态
  • 只是,为什么在这种情况下使用级联参数而不是经典参数?
  • 我都试过了,都没有像我预期的那样工作
  • 可能是因为更新不起作用?

标签: blazor blazor-client-side


【解决方案1】:

好的,我刚收到您的问题。这是您的 UpdateTodo 方法:
异步方法必须返回 Task 或 ValueTask。更新您的代码:

public async Task UpdateTodo(TodoItem todoItem)
{
    await Http.PutAsJsonAsync("todo", todoItem);
    await RefreshTodos();
}

【讨论】:

  • 没有工作行为与“任务”完全相同
  • @DiogoNeves 你检查浏览器控制台日志了吗?
  • @DiogoNeves - 不过,Task 更好。您用来调用它的 lambda 是另一个 async void,更难看到。它们是即火即忘,您无法控制此处的操作顺序。
  • @aguafrommars console.log 中没有任何内容;
  • @HenkHolterman 实际上这可能是一个赛车条件,让我看看我能用它做什么。
【解决方案2】:

我想通了!

@bind="@TodoItem.TaskName"默认执行onChange

onInput 显然发生在 onChange 之前,因此在屏幕截图中,当我在其后面添加 1 个字符时,这意味着它没有更新 TodoItem.TaskName,因为这是下一步。

如果我真的想在每次击键时调用 API,我需要将其更改为:

@bind-value="@TodoItem.TaskName" @bind-value:event="oninput" onchange="@UpdateCallback"

通过这种方式,我将绑定更改为发生onInput,并调用UpdateCallback onChange。 因为onInput happens first 我在onChange 上获得了更新的值,因此传递了正确的值。

来源:https://github.com/dotnet/aspnetcore/issues/15554 他的错误和我一模一样

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-12
    • 2021-08-22
    • 1970-01-01
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2014-03-09
    相关资源
    最近更新 更多