英文:
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 ?
<h3>LocalStorageWithBlazoredStorage</h3>
@if (storeValue!=null && storeValue.Length>0)
{
<p> Current stored value is @storeValue.</p>
}
else
{
<p> Current stored value for user not set</p>
}
<p>Remember for 2 weeks or be subject to 2 factor authentication each time</p>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" onclick="@SaveTwoFactorContactInfo" id="flexCheckDefault">
<label class="form-check-label" for="flexCheckDefault">
Remember this computer
</label>
</div>
<button type="button" class="btn-success" onclick="@ReadLocalStorage">Read Local Storage</button>
@code {
private string storeValue = string.Empty;
private ContactInfo twoFacInfo = new ContactInfo();
private const string TwoFactor = "TwoFactorVerifInfo";
private void SaveTwoFactorContactInfo()
{
// persist an object
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 = $"Stored value for {twoFacInfo.LastName} {twoFacInfo.TextNumber} chose trust this PC : {twoFacInfo.trustThisPc}";
}
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<ContactInfo>(TwoFactor);
storeValue = $"Stored value for {twoFacInfo.LastName} {twoFacInfo.TextNumber} chose trust this PC : {twoFacInfo.trustThisPc}";
Console.WriteLine(" Ok");
}
}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<ContactInfo>(TwoFactor);
storeValue = $"Stored value for {twoFacInfo.LastName} {twoFacInfo.TextNumber} chose trust this PC : {twoFacInfo.trustThisPc}";
Console.WriteLine(" Ok");
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!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论