0
votes

Composant d'actualisation côté client Blazor

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.


6 commentaires

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: <


3 Réponses :


1
votes

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 signature au lieu de async void .


3 commentaires

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 =)



-1
votes

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(); 

    }

}


1 commentaires

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.



2
votes

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.


2 commentaires

Henk, si vous avez le temps, pouvez-vous expliquer brièvement pourquoi votre «mélange» fonctionne.


C'est parce que lorsque votre code 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

Loading...