J'essaie de comprendre comment actualiser le composant côté client après un clic sur le bouton.
Lien de référentiel avec exemple: https://github.com/ovie91/RefreshComponent
Site / test ou depuis le test du menu de navigation
Donc je avoir la méthode OnInitializedAsync qui récupère les données de l'API
@page "/test" @inject HttpClient Http @if (result == null) { <p>Loading...<p> } else { @result <button @onclick="(() => ButtonClick())">Click</button> } @code { private APIObject result; protected override async Task OnInitializedAsync() { result = await (some API Call); } private async void ButtonClick() { await (some API Call); result = null; this.StateHasChanged(); <--- Doesnt work :< } }
Ensuite, j'ai une méthode connectée au bouton
private async void ButtonClick() { await (some API Call); result = null; this.StateHasChanged(); <--- Doesnt work :< }
J'ai a essayé d'utiliser this.StateHasChanged (); mais il n'y a pas eu de réaction. Pour contourner le problème, je peux vous forcer à naviguer à nouveau vers le même site Web, mais cette actualisation du site Web "Tout" mais pas un composant.
Avez-vous des idées sur la façon de le gérer?
code entier (réduit au minimum):
protected override async Task OnInitializedAsync() { result = await (some API Call); }
Mettre à jour Je veux actualiser le composant afin que OnInitializedAsync soit à nouveau déclenché et cela signifierait que je n'ai pas à exécuter à nouveau le même code après un clic sur le bouton. J'espère que vous comprenez ce que je veux dire.
3 Réponses :
De ici :
Blazor utilise un contexte de synchronisation (SynchronizationContext) pour appliquer un seul thread logique d'exécution. Les méthodes de cycle de vie d'un composant et tous les rappels d'événement déclenchés par Blazor sont exécutés sur le contexte de synchronisation.
Le contexte de synchronisation de Blazor Server tente d'émuler un environnement à thread unique afin qu'il corresponde étroitement au modèle WebAssembly dans le navigateur, qui est à thread unique. À tout moment donné, le travail est effectué sur exactement un thread, donnant l'impression d'un seul thread logique. Aucune opération ne s’exécute simultanément.
Pour enet répondre , vous devez utiliser async Task code > signature au lieu de
async void
.
Je ne pense pas que le problème soit lié à SynchronizationContext ...
Repo Link avec exemple: github.com/ovie91/RefreshComponent Site / test ou depuis le test du menu de navigation
@ user3574248 Mais cela fonctionne. Il se met à jour avec la valeur de result
Même avec async void
=)
J'ai déplacé l'appel d'API vers une autre méthode et à l'intérieur de OnInitializedAsync je l'ai appelé.
Ensuite, lorsque je réinitialise la variable de résultat pour voir l'état de chargement, je suis capable de "rafraîchir" le composant pour y parvenir, vous devez l'ajouter. this.StateHasChanged()[
Maintenant, j'ai un composant réactif aux mises à jour en cours :)
@page "/test" @using System.Threading; @inject HttpClient Http @if (result == null) { <h3>Loading</h3> } else { @result <button @onclick="(() => ButtonClick())">Click</button> } @code { private string result; protected override async Task OnInitializedAsync() { await GetData(); } private async Task GetData() { var APICall = await Http.GetAsync("SomeAPI"); Random rnd = new Random(); Thread.Sleep(2000); result = "Random Number: " + rnd.Next(); } private async Task ButtonClick() { await Http.GetAsync("SomeAPIcall"); result = null; // required to see loading state. this.StateHasChanged(); // when added model is refreshed and Loading state is visible. await GetData(); } }
mon expérience avec le développement Web est de 0, je suis juste en train d'apprendre c #, blazor et .net core. Ce n'est peut-être pas la bonne approche, mais cela fonctionne, donc je n'ai aucune idée de ce que vous essayez d'accomplir avec vos commentaires.
Pour obtenir le résultat souhaité, il vous suffit de mélanger un peu les lignes, de:
private async Task GetData() { await Task.Yield(); // release the thread for rendering var APICall = await Http.GetAsync("SomeAPI"); Random rnd = new Random(); Thread.Sleep(2000); // Task.Delay() is much preferred result = "Random Number: " + rnd.Next(); }
à:
var APICall = await Http.GetAsync("SomeAPI"); Thread.Sleep(2000);
cependant, à partir de votre réponse, nous obtenons
private async void ButtonClick() { result = null; this.StateHasChanged(); // should show '<h3>Loading</h3>' now await (some API Call); }
Cela devrait fonctionner lorsque Http.GetAsync ("SomeAPI");
est vraiment un appel asynchrone et pas seulement un stand -en pseudo code. Parce que Thread.Sleep (2000);
va vraiment geler les choses.
Si vous voulez vous assurer:
private async void ButtonClick() { await (some API Call); result = null; this.StateHasChanged(); <--- Doesnt work :< }
Thread.Sleep () est approprié pour simuler du code intensif en CPU (pas en E / S). Donc, je ne dis pas que c'est faux, mais soyez conscient de la différence.
Et il est préférable de créer des gestionnaires d'événements async Task
au lieu de async void
mais ce n'est pas le problème direct ici.
Henk, si vous avez le temps, pouvez-vous expliquer brièvement pourquoi votre «mélange» fonctionne.
C'est parce que lorsque votre code Loading... attend
est quelque chose, le thread est libéré et peut mettre à jour l'interface utilisateur. Définissez donc la variable sur null
avant en attendant de voir le
Cela vous aiderait si vous postiez un peu plus de code. Vous ne nous montrez pas le soir quand / où vous appelez StateHasChanged
Dans le bouton Click - j'ai mis à jour le post :)
Quelles propriétés essayez-vous de mettre à jour? - qui sont dans la vue de l'utilisateur
J'ai ajouté "tout le code", j'essaye de mettre à jour à nouveau tout ce composant Page. Mes données sont donc actualisées après avoir cliqué sur le bouton
Vous définissez le résultat sur null en cliquant sur le bouton
Oui, car lors de l'actualisation de la page, elle doit être à nouveau remplie avec le résultat. Je peux supprimer cette ligne et cela ne fonctionnera toujours pas comme je le souhaite: <