Closed Rhywden closed 2 years ago
What do you mean by "other source", JavaScript calling into Blazor?
If so, are you wrapping your called method code in InvokeAsync?
Well, I have a SignalR hub which uses Dispatch()
to announce changes when it receives data.
I'll detail what the page itself and the SignalR client of the Blazor WASM application are looking like:
The page:
@using AnliegenWASM.Shared.HubData
@using Fluxor
@implements IDisposable
@foreach(raum as RaumState.Value.Räume) {
...
}
@code {
[Inject]
private IState<RaumState> RaumState { get; set; }
protected override void OnInitialized()
{
RaumState.StateChanged += StateChange;
}
private async void StateChange(object? source, System.EventArgs e)
{
await InvokeAsync(StateHasChanged);
}
public void Dispose()
{
RaumState.StateChanged -= StateChange;
}
This version is working and does pick up on any changes the SignalR client dispatches upon receiving data.
However, if I use @inherits Fluxor.Blazor.Web.Components.FluxorComponent
instead of subscribing to the StateChanged
event, nothing happens. Reading the documentation, I got the impression that inheriting would get rid of the requirement for this subscription?
The SignalR client lives on the MainLayout.razor
(for now) and basically does this:
@using AnliegenWASM.Shared.Hub
@using AnliegenWASM.Shared.HubData
@using Fluxor
<Layoutstuff>
@body somewhere
</Layoutstuff>
@code {
[Inject]
public IDispatcher Dispatcher { get; set; }
[Inject]
private IState<RaumState> RaumState { get; set; }
protected override async Task OnInitializedAsync() {
//some other async tasks
SignalRService.RegisterOnRaum((raum, method) =>
{
if (method == HubMethod.Create)
{
Dispatcher.Dispatch(new AddOneRaumAction(NeuerRaum: raum));
} else if(method == HubMethod.Delete)
{
Dispatcher.Dispatch(new DeleteOneRaumAction(ZuLöschenderRaum: raum));
} else if(method == HubMethod.Update)
{
Dispatcher.Dispatch(new UpdateOneRaumAction(ZuÄndernderRaum: raum));
}
});
}
Basically, that's it. Unless you need the Action
and Reducer
definitions as well?
As an experiment, try
InvokeAsync(() =>
{
if (method == HubMethod.Create)
{
Dispatcher.Dispatch(new AddOneRaumAction(NeuerRaum: raum));
} else if(method == HubMethod.Delete)
{
Dispatcher.Dispatch(new DeleteOneRaumAction(ZuLöschenderRaum: raum));
} else if(method == HubMethod.Update)
{
Dispatcher.Dispatch(new UpdateOneRaumAction(ZuÄndernderRaum: raum));
}
});
That did the trick. Might be worthwhile to add that to the docs?
Anyways, thanks for your help!
It's a Blazor thing that you have to InvokeAsync any code executed from outside of Blazor, to ensure you only ever have a single thread running on your code.
I would have expected Fluxor to deal with this successfully, but it's good that you now know :)
Indeed.
I basically followed the instructions, added
to the top of the page, injected the proper state like so:
but when some other source dispatches a change to the
RoomState
it does not get picked up. It's only when I switch pages or manually subscribe toRoomState.StateChanged
and callStateHasChanged
from the event handler that the changes get picked up.