Blazor 页面在本地存储执行之前加载,导致刷新失败。

huangapple go评论59阅读模式
英文:

Blazor Page Loaded before localstorage executes and fails to refresh

问题

我的简单的Blazor.razor页面可以读取本地存储,但似乎是在页面显示后才执行。需要点击按钮才能检索值。看起来我应该能够强制刷新。但如何做呢?

<h3>LocalStorageWithBlazoredStorage</h3>
@if (storeValue != null && storeValue.Length > 0)
{
    <p>当前存储的值为 @storeValue。</p>
}
else
{
    <p>用户的当前存储值未设置。</p>
}
<p>记住两周,否则需要进行两因素身份验证。</p>

<div class="form-check">
    <input class="form-check-input" type="checkbox" value="" onclick="@SaveTwoFactorContactInfo" id="flexCheckDefault">
    <label class="form-check-label" for="flexCheckDefault">
        记住这台计算机
    </label>
</div>

<button type="button" class="btn-success" onclick="@ReadLocalStorage">读取本地存储</button>

@code {

    private string storeValue = string.Empty;

    private ContactInfo twoFacInfo = new ContactInfo();
    private const string TwoFactor = "TwoFactorVerifInfo";
    private void SaveTwoFactorContactInfo()
    {
        // 持久化一个对象
        ContactInfo twoFacInfo = new ContactInfo
        {
                LastName = "Jones",
                TextNumber = "425-123-4567",
                trustThisPc = true
        };

        localStorage.SetItemAsync(TwoFactor, twoFacInfo);
    }

    private async Task ReadLocalStorage()
    {
        twoFacInfo = await localStorage.GetItemAsync<ContactInfo>(TwoFactor);
        storeValue = $"存储的值为 {twoFacInfo.LastName} {twoFacInfo.TextNumber} 选择了信任此计算机:{twoFacInfo.trustThisPc}";
    }

    protected override async Task OnInitializedAsync()
    {
        ReadLocalStorage();// 页面启动
    }

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {    // 这不会在加载页面时更新页面
        // 当单击完成时,这会再次触发,firstRender 为 false,但 storeValue 已经加载
        if (firstRender)
        {
            twoFacInfo = await localStorage.GetItemAsync<ContactInfo>(TwoFactor);
            storeValue = $"存储的值为 {twoFacInfo.LastName} {twoFacInfo.TextNumber} 选择了信任此计算机:{twoFacInfo.trustThisPc}";
            Console.WriteLine("好的");
        }
    }
}

断点显示页面已显示,并且 OnAfterRenderAsync 已触发,但似乎为时已晚...
其次,如何在 firstRender 时读取值?是否可以读取?

期望不使用按钮来检索本地存储的值
在StackOverflow上搜索时,找到了类似的问题...但似乎只在再次调用时起作用...

英文:

My simple blazor.razor page can read local storage but seems to do after page is displayed. It takes a button to retrieve value. Seems like I should be able to force a refresh. But how ?

&lt;h3&gt;LocalStorageWithBlazoredStorage&lt;/h3&gt;
@if (storeValue!=null &amp;&amp; storeValue.Length&gt;0)
{
    &lt;p&gt; Current stored value is  @storeValue.&lt;/p&gt;
}
else
{
    &lt;p&gt; Current stored value for user not set&lt;/p&gt;
}
&lt;p&gt;Remember for 2 weeks or be subject to 2 factor authentication each time&lt;/p&gt;

&lt;div class=&quot;form-check&quot;&gt;
    &lt;input class=&quot;form-check-input&quot; type=&quot;checkbox&quot; value=&quot;&quot; onclick=&quot;@SaveTwoFactorContactInfo&quot; id=&quot;flexCheckDefault&quot;&gt;
    &lt;label class=&quot;form-check-label&quot; for=&quot;flexCheckDefault&quot;&gt;
        Remember this computer
    &lt;/label&gt;
&lt;/div&gt;

&lt;button type=&quot;button&quot; class=&quot;btn-success&quot; onclick=&quot;@ReadLocalStorage&quot;&gt;Read Local Storage&lt;/button&gt;


@code {

    private string storeValue = string.Empty;

    private ContactInfo twoFacInfo = new ContactInfo();
    private const string TwoFactor = &quot;TwoFactorVerifInfo&quot;;
    private void SaveTwoFactorContactInfo()
    {


        // persist an object
        ContactInfo twoFacInfo = new ContactInfo
        {
                LastName = &quot;Jones&quot;,
                TextNumber = &quot;425-123-4567&quot;,
                trustThisPc = true
        };



        localStorage.SetItemAsync(TwoFactor, twoFacInfo);

    }

    private async Task ReadLocalStorage()
    {
        twoFacInfo = await localStorage.GetItemAsync&lt;ContactInfo&gt;(TwoFactor);
        storeValue = $&quot;Stored value for {twoFacInfo.LastName} {twoFacInfo.TextNumber} chose trust this PC : {twoFacInfo.trustThisPc}&quot;;
    }

    protected override async Task OnInitializedAsync()
    {
        ReadLocalStorage();// page start
    }

    protected async override Task OnAfterRenderAsync(bool firstRender)   // this doesnt update the page on load either 
    {    // this fires again when click is done, firstRender is false but storeValue already loaded
        if (firstRender)
        {
            twoFacInfo = await localStorage.GetItemAsync&lt;ContactInfo&gt;(TwoFactor);
            storeValue = $&quot;Stored value for {twoFacInfo.LastName} {twoFacInfo.TextNumber} chose trust this PC : {twoFacInfo.trustThisPc}&quot;;
            Console.WriteLine(&quot; Ok&quot;);
           
        }
    }type here

A breakpoint shows page displayed and OnAfterRenderAsync fires but seems to late...
2nd how can I read the value firstRender. ? Is it possible to read

Expecting to not use a button to retrieve localStorage values
Googled StackOverflow came upon similar issue...but only seems to work if called again...

答案1

得分: 0

以下是翻译好的部分:

嗨,你说得对,本地存储是在页面加载后访问的,因为这正是你编程要发生的事情。OnAfterRender 方法在页面呈现/加载后触发。为什么不在 OnInitialized 或者,因为你似乎需要异步操作,OnInitializedAsync 中访问本地存储?

此外,回答你的问题:

我如何读取值 firstRender?是否可能读取?

是的,可以读取,你可以使用 Console.WriteLine(FirstRender),它将显示在你的网站控制台中。但如果你知道它的作用,就没有必要读取它。bool FirstRender 在页面的第一次呈现时的值为 true,因此当页面首次对用户可见时为 true

此外,我注意到你的 OnInitalized 方法是错误的;没关系。你只需要等待你的 ReadLocalStorage 方法,因为它是异步任务类型。


protected override async Task OnInitializedAsync()
{
    await ReadLocalStorage();// 页面启动
}

你的注释还说

这也不会在加载时更新页面

如果是这样,你应该能够在你的 OnAfterRender 方法中添加 StateHasChanged 方法。我在这里展示一下:


protected async override Task OnAfterRenderAsync(bool firstRender)   // 这也不会在加载时更新页面
{    // 当单击完成时再次触发,firstRender 为 false,但 storeValue 已经加载
    if (firstRender)
    {
        twoFacInfo = await localStorage.GetItemAsync<ContactInfo>(TwoFactor);
        storeValue = $"为{twoFacInfo.LastName} {twoFacInfo.TextNumber} 存储的值选择信任此计算机:{twoFacInfo.trustThisPc}";
        Console.WriteLine("好");
        StateHasChanged();
    }
}

StateHasChanged 方法由 ASP.NET 提供,它本质上告诉 Blazor 重新加载组件,因为已经发生了可以影响它们的变化。

希望这有所帮助!

英文:

Heyo, you're right that the local storage is being accessed after the page loads, because that's exactly what you've programmed to happen. The OnAfterRender method is fired after the page has rendered/loaded. Why don't you access the local storage in the OnInitialized or, since you seem to need the Async, OnInitializedAsync?

Also, to answer your question of
> how can I read the value firstRender. ? Is it possible to read

Yes, it's possible to read, you can use a Console.WriteLine(FirstRender) for that and it'll show in your website's console. However there's no reason to read it if you know what it does. The bool FirstRender is of value true on the very first render of the page, so when the page is initially visible to the user.

Also, I noticed your OnInitalized method was wrong; no big deal. You just need to await your ReadLocalStorage method because it is of type async Task


protected override async Task OnInitializedAsync()
{
    await ReadLocalStorage();// page start
}

Your comments also say
> this doesnt update the page on load either

And if that's true, you should be able to add a StateHasChanged method to your OnAfterRender method. I'll show it here:


    protected async override Task OnAfterRenderAsync(bool firstRender)   // this doesnt update the page on load either 
    {    // this fires again when click is done, firstRender is false but storeValue already loaded
        if (firstRender)
        {
            twoFacInfo = await localStorage.GetItemAsync&lt;ContactInfo&gt;(TwoFactor);
            storeValue = $&quot;Stored value for {twoFacInfo.LastName} {twoFacInfo.TextNumber} chose trust this PC : {twoFacInfo.trustThisPc}&quot;;
            Console.WriteLine(&quot; Ok&quot;);
            StateHasChanged();
        }
    }

The StateHasChanged method is provided by ASP.NET and it essentially tells Blazor to reload the components because something has changed that can effect them.

Hope this helps!

huangapple
  • 本文由 发表于 2023年3月4日 05:19:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75631969.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定