簡體   English   中英

Blazor(客戶端)StateHasChanged() 不更新頁面

[英]Blazor (Client-side) StateHasChanged() not updating page

我的頁面(組件)上有一個按鈕,單擊時會調用 Refresh() 方法。 此方法然后調用 StateHasChanged(),但不會重新加載頁面。 GetData() 正在調用外部 API 以從數據庫加載數據。

<button class="btn btn-warning" @onclick="Refresh">Refresh</button>

code {

protected override async Task OnInitializedAsync()
    {
        try
        {
            await GetData();
            base.OnInitialized();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

protected async Task GetData()
    {
        try
        {
            results = await HttpClient.GetJsonAsync<Results[]>(ServiceEndpoints.GET_RESULTS);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error retrieving data from Oracle.", ex.Message);
        }
    }

public void Refresh()
        {
            StateHasChanged();          
        }

我的頁面(組件)還有一個表單,該表單具有可以更改的預加載輸入。 我希望用戶能夠編輯表單,但能夠通過單擊按鈕來刷新頁面以取回原始數據。 這是在以前版本的 Blazor 上工作的,是否存在已知問題?

@page "/"
@inherits IndexBase

<EditForm Model="@results">
<label><strong>Select a job to view its current parameters</strong></label>
<div class="currentJobForm">

    <InputSelect id="jobSelect" @bind-Value="jobSelected">
        @foreach (var items in results)
        {
            <option value="@items.JOB_NAME">@items.JOB_NAME</option>
        }
    </InputSelect>
    <button class="btn btn-warning" @onclick="SaveChanges" disabled="@IsDisabled">Save</button>
    <button class="btn btn-warning" @onclick="Refresh">Refresh</button>
    <button class="btn btn-danger" @onclick="DeleteJob">Delete Job</button>
</div>    
    <label><strong>Notify Parameters</strong></label>
    <div class="notifyParametersForm">
        @foreach (var item in results.Where(i => i.JOB_NAME == jobSelected))
        {
            <div class="issueDescription">
                <label><strong>Issue Description</strong></label>
                <InputText id="issueDesc" @bind-Value="item.JOB_HEADER" placeholder="Enter New Issue Description" />
            </div>
            <div class="sendSlack">
                <label><strong>Send Slack</strong></label>
                <InputSelect id="sendSlackSelect" @bind-Value="item.SENDSLACK">
                    @foreach (var items in InitializeData.SendSlacks)
                    {
                        <option value="@items.SendSlackName">@items.SendSlackName</option>
                    }                        
                </InputSelect>
            </div>
            <div class="slackUser">
                <label><strong>Slack User</strong></label>
                <InputText id="slackUser" @bind-Value="item.SLACK_USER" placeholder="Enter New Slack User" />
            </div>
            <div class="slackChannel">
                <label><strong>Slack Channel</strong></label>
                <InputSelect id="sendSlackChannel" @bind-Value="item.SLACK_CHANNEL">
                    @foreach (var items in InitializeData.SlackChannels)
                    {
                        <option value="@items.SlackChannelName">@items.SlackChannelName</option>
                    }                        
                </InputSelect>
            </div>
            <div class="slackUrl">
                <label><strong>Slack URL</strong></label>
                <InputText id="slackUrlTextBox" @bind-Value="item.SLACK_URL" placeholder="Enter New Slack Url" />
            </div>
            <div class="sendMail">
                <label><strong>Send Mail</strong></label>
                <InputSelect id="sendMailSelect" @bind-Value="item.SENDMAIL">
                    @foreach (var items in InitializeData.SendMails)
                    {
                        <option value="@items.SendMailName">@items.SendMailName</option>
                    }
                </InputSelect>
            </div>
            <div class="mailFrom">
                <label><strong>From:</strong></label>
                <InputText id="from" @bind-Value="item.MAILFROM" placeholder="Enter New Mail From" />
            </div>
            <div class="mailTo">
                <label><strong>To:</strong></label>
                <InputText id="to" @bind-Value="item.MAILTO" placeholder="Enter New Mail To" />
            </div>
            <div class="subject">
                <label id="subjectLabel"><strong>Subject:</strong></label>
                <InputText id="subject" @bind-Value="item.EMAIL_SUBJECT" placeholder="Enter New Subject" />
            </div>
        }
    </div>
</div>

正如所有其他答案所解釋的那樣,有多種方法可以正確重置您的表單,但除了 BrinkDaDrink 答案之外,沒有一種方法會告訴您如何通過按一下按鈕來刷新頁面。

在我看來,BrinkDaDrink 答案增加了不必要的復雜性。

我的解決方案是創建一個名為 refresh 的空組件頁面,如下所示:

@page "/refresh"
@inject NavigationManager NavigationManager

@code {

    protected override void OnInitialized()
    {
        NavigationManager.NavigateTo("");
    }

}

此頁面將立即重定向到您的原始頁面,立即刷新頁面和所有數據。

您可以在原始頁面中創建刷新方法,如下所示:

public void RefreshPage()
{
    NavigationManager.NavigateTo("refresh");
}

這比迄今為止提供的任何其他解決方案更快地解決您提到的問題:

我希望用戶能夠編輯表單,但能夠通過單擊按鈕來刷新頁面以取回原始數據

您還可以使用它通過將以下內容添加到刷新頁面來將參數傳遞到刷新頁面:

@page "/refresh"
@page "/refresh/{text}"
@inject NavigationManager NavigationManager

@code {
    [Parameter]
    public string Text { get; set; }

    protected override void OnInitialized()
    {
        NavigationManager.NavigateTo(Text);
    }

}

您需要將值設置回其原始值。 StateHasChanged不會刷新頁面。 它重置組件以檢查 RenderTree 以查看是否應該更新 dom 元素 - 但由於您的值沒有更改,因此不會更新您正在尋找的方式。

調用GetData()而不是StateHasChanged應該適用於您的情況,但您可能希望存儲值而不是再次點擊 API。

我簡化了您的代碼以提供一個工作示例:

    @page  "/update-test"
<EditForm Model="@Item">
    <div class="notifyParametersForm">
    </div>
    <div class="mailFrom">
        <label><strong>From:</strong></label>
        <InputText id="from" @bind-Value="Item.MAILFROM" placeholder="Enter New Mail From" />
    </div>
    <div class="mailTo">
        <label><strong>To:</strong></label>
        <InputText id="to" @bind-Value="Item.MAILTO" placeholder="Enter New Mail To" />
    </div>
    <div class="subject">
        <label id="subjectLabel"><strong>Subject:</strong></label>
        <InputText id="subject" @bind-Value="Item.EMAIL_SUBJECT" placeholder="Enter New Subject" />
    </div>

    <button class="btn btn-warning" @onclick="ResetInputs">Refresh</button>
</EditForm>

@code {


    EmailItem Item;
    protected override async Task OnInitializedAsync()
    {
        try
        {
            GetData();
            base.OnInitialized();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

    protected void GetData()
    {
        Item = new EmailItem()
        {
            MAILFROM = "testfrom@test.com",
            MAILTO = "testto@test.com",
            EMAIL_SUBJECT = "subject",
        };
    }

    public void ResetInputs()
    {
        GetData();
    }

    public class EmailItem
    {
        public string MAILTO { get; set; }
        public string MAILFROM { get; set; }
        public string EMAIL_SUBJECT { get; set; }
    }
}

我是通過綁定一個字符串值來實現的。 您不必在正文頁面上顯示該值即可使其工作。 我將字符串從大寫更改為小寫。 有趣的是,這只適用於字符串值。

NAVMENU ----------------------
  <button type="button" class="btn btn-warning border-secondary" @onclick="runSearch">Search</button>

@code {
    public string pageReload = "Search";

 private void runSearch()
    {
        if (pageReload == "Search") { pageReload = "search"; } else { pageReload = "Search"; }
        NavigationManager.NavigateTo($"/Page2/{pageReload}", false);
    }
}

Page 2------------------------------------------------------------------------

@page "/Datatest2/{pageReload}"

<h1>page will now refresh every time</h1>


@code{
    [Parameter]
    public string pageReload { get; set; }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM