DEV Community

Advanced Blazor State Management Using Fluxor, part 7 - Client-to-Client comms with SignalR

Eric King on May 08, 2021

This is the seventh in a short series of blog posts where I will go beyond the introductory level and dig a bit deeper into using the Fluxor libra...
Collapse
 
martinandersen profile image
Martin Andersen

Very interesting πŸ€”I just started with SignalR and right now I only receive messages.
So I want to dip my toes in Fluxor using the SubscribeToAction that I find much more β€œclean” than using multiple CascadingValues
So what does a minimal hub look like? And how do I dispose the hub when my program stops?
Have created a gist instead off trying to attach a lot of code.

Collapse
 
mr_eking profile image
Eric King

Looks good! I do like the ability to incorporate a SignalR hub into a Fluxor store. It opens up a lot of possibilities.

Collapse
 
martinandersen profile image
Martin Andersen

Thanks. Does Fluxor dispose Effect classes?

Collapse
 
rf0 profile image
rf-0

Really enjoyed these series! thanks!

Collapse
 
martinandersen profile image
Martin Andersen

Thanks has been looking for a real world example with 2-way data binding and API calls.
Maybe it's just me. But I think most users expect to see the initial state when the enter a webpage. People are also used to press F5 to refresh a page.

I know the weather forecast was an example on using API calsl. But in the real world people want a fresh weather forecast 😊

Any way, awesome job writing this go to guide on using Fluxor in Blazor

Collapse
 
whitelabeldevelopment profile image
Neil Thompson

Great series. Thank you

Collapse
 
jcoble profile image
jcoble

Hi Eric,

I have a question on the WeatherStore example. Let's say I needed to wait for the LoadForecasts() to be completed and then do more async tasks afterword's that was dependent on the forecasts array. This would then need to be in the OnInitializedAsync override. How would I wait for the LoadForecasts to finish and then do the rest of the async tasks that I need to do? Right now, if I test it, once it hits the await Http.GetFromJson(...)... it then continues on with the rest of the code, even though the LoadForecasts effect has not yet completed. Below is the code I'm referring to in your series that I would like to put in the OnInitializedAsync override and put code after it once the LoadForecasts() has finished.

private WeatherForecast[] forecasts => WeatherState.Value.Forecasts;
private bool loading => WeatherState.Value.Loading;

protected override void OnInitialized()
{
    if (WeatherState.Value.Initialized == false)
    {
        LoadForecasts();
        Dispatcher.Dispatch(new WeatherSetInitializedAction());
    }
    base.OnInitialized();
}

private void LoadForecasts()
{
    Dispatcher.Dispatch(new WeatherLoadForecastsAction());
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jcoble profile image
jcoble

I answered my own question I'm pretty sure. I need to SubscribeToAction and then load the rest of the data once that has been called. Below is some code that in my actual app where I'm waiting on UserSetUserResponseAction to be called then loading the rest of the component data. I need the CurrentUser to be able to finish the component data, so if it is not Initialized yet, then load the user data by dispatching the UserLoadUserResponseAction, else just use the UserStore.Value.CurrentUser.

I'd like to be able to just use UserStore.Value.CurrentUser instead of using another property that I'm setting, from the action.UserResponse, but the UserSetUserResponseAction callback is called before the reducer is which sets it, so UserStore.Value.CurrentUser is not yet set, when the rest of the code is run.

    protected override void OnInitialized()
    {
        IsLoading = true;
        isFirstRender = true;
        SubscribeToAction<UserSetUserResponseAction>(async action => await LoadComponentData(action.UserResponse));
        if (UserState.Value.Initialized == false)
        {
            loadUserDate();
            Dispatcher.Dispatch(new UserSetInitalizedAction());
        }
        else
        {
            LoadComponentData(UserState.Value.CurrentUser);
        }
        base.OnInitialized();
    }

    private void loadUserDate()
    {
        Dispatcher.Dispatch(new UserLoadUserResponseAction());
    }

    private async Task LoadComponentData(UserResponse userResponse)
    {
        CurrentUser = userResponse;
        await loadTrainingCourses();
        HubConnection = HubConnection.TryInitialize(_navigationManager);
        if (HubConnection.State == HubConnectionState.Disconnected)
        {
            await HubConnection.StartAsync();
        }

        IsLoading = false;
        StateHasChanged();
    }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mr_eking profile image
Eric King

In the WeatherStore, you'll notice that the LoadForecasts EffectMethod dispatches the WeatherLoadForecastsSuccessAction to indicate that the forecasts have been loaded. If I want to have some action happen after the forecasts have been loaded, I can SubscribeToAction<WeatherLoadForecastsSuccessAction> and put whatever I need to do in there.

It looks like that's what you're doing with the SubscribeToAction<UserSetUserResponseAction> so I think we're on the same page there.

Collapse
 
quinton profile image
quintonv

Thank you so much for this series of articles and taking the time to illustrate and explain everything along the way. This has been instrumental in helping me learn Blazor.

Collapse
 
jcoble profile image
jcoble

Thanks so much for the detailed and thorough tutorial series. I definitely learned so much more than the tutorial videos I've watched. Great job!

Collapse
 
rhermans profile image
rhermans

Thanks for this great walkthru, made it so much easier to make the switch from angular ngrx to fluxor.

Collapse
 
vbfan profile image
Razmi Martinez

Please could you share the code ?
Thank you

Collapse
 
mr_eking profile image
Eric King
Collapse
 
vbfan profile image
Razmi Martinez

Thank you