Giter VIP home page Giter VIP logo

fluxor's People

Contributors

82amp avatar bitobrian avatar bradtwurst avatar buvinghausen avatar codedevote avatar dannybies avatar darthkurt avatar dependabot[bot] avatar dharmaturtle avatar dmitry-pavlov avatar eraph avatar giannhsr avatar gitter-badger avatar ievangelist avatar kuraiandras avatar mfmadsen avatar mrpmorris avatar neil-rubens avatar peterbozso avatar samuelschnurr avatar stefh avatar steventcramer avatar teknikaali avatar thezevascon avatar uhfath avatar werzl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fluxor's Issues

No parameterless constructor defined for type 'FluxorTest.App'

Hello,

I'm brand new with Fluxor, so please forgive me if I'm doing something stupid.

I'm trying to follow the first tutorial, and am getting a compilation error.

I added the package, then added the following two lines to the ConfigureServices method in Startup.cs...

  services.AddScoped<App>();
  services.AddFluxor(o => o
    .ScanAssemblies(typeof(Program).Assembly));

I know the tutorial says to put them in Program.cs, but it didn't seem to make any difference, and everything else I've seen says to add your services in Startup.cs

I then added a class called App and copied in the code. At this point, I tried to run the project, but had an error in the browser window of "No parameterless constructor defined for type 'FluxorTest.App'" which makes sense, as there isn't one.

What did I do wrong? Thanks

Prevent endless loop detection

Problem

At the moment Fluxor detects self-inflicted endless loop and breaks out of the cycle. This loop started to happen once Effects were executed within a task (so that exceptions could be caught without holding up the pipeline).

In previous versions the routing middleware was able to check the browser's current URL against state and only dispatch an action if it is different, and this was sufficient because although effects can be async, the routing middleware's effect didn't await so executed synchronously.

Now that effects are all run inside an awaited task, this cannot happen synchronously, so by the time the middle checks the state against the current URL the URL could have changed due to an auth redirect to a sign-in page. At which point the middleware updates the browser URL, taking us back to the app, at which point the auth redirects us back to the sign-in page, ad ininitum.

Solution

Change the effects dispatcher so it executes each task outside of the Task.Run (capturing any exceptions to a list), and then only run the Task.WhenAll inside the Task.Run. This will give synchronous effects the opportunity to run and complete immediately.

May I use Fluxor in my book ?

Hi @mrpmorris

I plan to write a book in french for Blazor.
In a dedicated chapter, I want to talk about Redux pattern and how to use it with Blazor.
As I'm currently using Fluxor for a project, my editor needs me to ask : can I speak about Fluxor in my book and how to use it ?

Thanks for answering !

SubscribeToAction with NavigateTo throws an exception

In a Blazor WASM project, I am trying to handle the navigation to a new page once my HTTP method has completed successfully. My thinking is that I can then choose to remain on the page if I need to handle errors in the API call etc.

Using SubscribeToAction works unless I add a navigation call in the callback.: e.g.

         SubscribeToAction<AddItemResponseAction>(x =>
            {
                NavigationManager.NavigateTo("/");
            });

With the navigation call in place, I get Unhandled exception rendering component: Collection was modified; enumeration operation may not execute.

The exception is thrown by the line in the Notify method of the ActionSubscriber class (line #38):

foreach (Action<object> callback in callbacks)

If I change the previous Select query to persist (i.e. by adding a ToList() call), or change the foreach to foreach (Action<object> callback in callbacks.ToList()), the exception is not thrown.

It doesn't seem resolvable by unsubscribing from the actions. Is there a way I can resolve this in client code rather than modifying the ActionSubscriber class?

Thanks.

Discussion: Add analyzer warning for setters on inherited state classes

I'd like to add an optional analyzer package for Fluxor that would contain various analyzers specific to the library to assist with keeping flux implementations clean and warning users about anti-flux patterns. I think a great starting point would be to add an analyzer that would warn consumers when they've added a seter on one of their state classes to drive home the point that state should be immutable by nature.

Something akin to:

public class MyState
{
    public string CurrentMessage { get; set; } // Would throw an analyzer warning to remove the setter
}

I'd like to get your thoughts on this and a possible viable approach, should you see it fit for the library. I was thinking something along the lines of adding an optional class attribute to intended state classes (i.e. [FeatureState], or something of the like) when you've added a package reference to the analyzer library. I believe Rider/ReSharper will do this by default for users as a refactoring, whereas this analyzer would be a specific warning that might keep you from compiling should you choose so, but I think this opens up the library to adding more specific analyzers for future use cases.

Error with Microsoft.Graph

Hi, I'm trying to use Fluxor in combination with an API I wrote and Microsoft.Graph.

I'm getting this exception in the console:

WASM: Fluxor.Exceptions.StoreInitializationException: Store initialization error ---> System.NotSupportedException: The collection type 'Microsoft.Graph.IUserOwnedDevicesCollectionWithReferencesPage' on 'Microsoft.Graph.User.OwnedDevices' is not supported.
p.printErr @ blazor.webassembly.js:1

I need to get the members of an Azure AD Group and perform some operations on them.
Do you know if I need to set any parameter in order to be able to work with the Microsoft.Graph 3.0.1 nuget package?

Effects class instantiated twice?

In debugging an issue where state didn't appear to be affected by a dispatched action as expected following a page navigation, I found that an effects class (class with one or more methods marked [EffectMethod]) is instantiated twice. I'm new to Fluxor am not sure if this is expected, but it seems wrong. Is there any common mistake I could be making that would explain this behavior?

Most likely I don't completely understand how to share state between pages/components. I assumed that each time IState is injected into a component, it's always a reference to the same state object, so the state is already implicitly shared between pages. But maybe some special handling is required to accomplish this?

Fluxor does not work with LiveSharp.

Hi @mrpmorris,

I am using LiveSharp, a tool to rerender changes to the browser immediately. This tool sadly does not work with Fluxor at the moment.

I've reported the problem to the maintainer of LiveSharp, but he can't find the solution on his end, and it seems the problems lies in a missing try/catch when resolving assemblies with Fluxor. Is this something you can solve on your end?

More information can be found in the following issue: OYIon/LiveSharp#78

Why is the counter state saved in the store, but not the weather forecasts?

Still following the Blazor web tutorials (done the second one now), and I've noticed that when you click away from the counter page and then click back, the counter state is preserved, so if I click the button to increase the counter a few times, go to another page and come back, the number is the same as it was before, not reset to zero.

However, if I do the same with the fetch data page, the weather forecasts are reloaded. I noticed this as I was looking at what the IsLoading property was doing, and added a delay when loading the weather data. This allowed me to see the "Loading..." message, but also clarified that the data was reloaded every time I went back to the page.

How do I make it so that the weather data is also saved in the store and not reloaded? Thanks

State not changing when using custom base class

I have a custom base class that implements basic parameter validation and awaits for the store to initialize (MyComponent < MyBaseClass < FluxorComponent). This base class has an IState<State> property (not in MyComponent) and the components are not being refreshed.

Maybe something in the StateSubscriber, when calling GetStateDelegatesForType is not detecting properties in base classes?

Blazor - .NET Preview 8 - Breaks Fluxor - Not clear which part breaks

Hi Fluxor team,

Just grabbed the latest .NET Preview 8 + Blazor, but Fluxor seems to failed on initialisation.
It works previously with .NET Preview 7.

I attached the stacktrace from the browser, but I'm not sure which part breaks. Hopefully this can help the team to debug it.

Any advice to get this working?

Thanks!

blazor.webassembly.js:1 Debugging hotkey: Shift+Alt+D (when application has focus)
blazor.webassembly.js:1 blazor Loaded 9.36 MB resourcesThis application was built with linking (tree shaking) disabled. Published applications will be significantly smaller.
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Method has no body
System.BadImageFormatException: Method has no body
File name: 'Fluxor'
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure, Boolean allowClosed)
   at System.Delegate.CreateDelegate(Type type, MethodInfo method, Boolean throwOnBindFailure)
   at System.Delegate.CreateDelegate(Type type, MethodInfo method)
   at Fluxor.Store..ctor()
   at Fluxor.DependencyInjection.DependencyScanner.<>c__DisplayClass1_0.<RegisterStore>b__3(IServiceProvider serviceProvider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite callSite, RuntimeResolverContext argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, RuntimeResolverContext argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__1(ServiceProviderEngineScope p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[Store](IServiceProvider provider)
   at Fluxor.DependencyInjection.DependencyScanner.<>c.<RegisterStore>b__1_2(IServiceProvider serviceProvider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite callSite, RuntimeResolverContext argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, RuntimeResolverContext argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__1(ServiceProviderEngineScope p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.AspNetCore.Components.ComponentFactory.<>c__DisplayClass6_0.<CreateInitializer>g__Initialize|2(IServiceProvider serviceProvider, IComponent component)
   at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider, IComponent instance)
   at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider, Type componentType)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateComponent(Type componentType)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& frame, Int32 parentComponentId)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree)
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
f.printErr @ blazor.webassembly.js:1
f.preRun.push.window.Blazor._internal.dotNetCriticalError @ blazor.webassembly.js:1
_mono_wasm_invoke_js_unmarshalled @ dotnet.5.0.0-preview.8.20407.11.js:1
do_icall @ dotnet.wasm:1
do_icall_wrapper @ dotnet.wasm:1
interp_exec_method @ dotnet.wasm:1
interp_runtime_invoke @ dotnet.wasm:1
mono_jit_runtime_invoke @ dotnet.wasm:1
do_runtime_invoke @ dotnet.wasm:1
mono_runtime_try_invoke @ dotnet.wasm:1
mono_runtime_invoke @ dotnet.wasm:1
mono_wasm_invoke_method @ dotnet.wasm:1
Module._mono_wasm_invoke_method @ dotnet.5.0.0-preview.8.20407.11.js:1
call_method @ dotnet.5.0.0-preview.8.20407.11.js:1
set_task_result @ dotnet.5.0.0-preview.8.20407.11.js:1
(anonymous) @ dotnet.5.0.0-preview.8.20407.11.js:1
Promise.then (async)
js_to_mono_obj @ dotnet.5.0.0-preview.8.20407.11.js:1
f.preRun.push.window.Blazor._internal.getSatelliteAssemblies @ blazor.webassembly.js:1
_mono_wasm_invoke_js_unmarshalled @ dotnet.5.0.0-preview.8.20407.11.js:1
do_icall @ dotnet.wasm:1
do_icall_wrapper @ dotnet.wasm:1
interp_exec_method @ dotnet.wasm:1
interp_runtime_invoke @ dotnet.wasm:1
mono_jit_runtime_invoke @ dotnet.wasm:1
do_runtime_invoke @ dotnet.wasm:1
mono_runtime_invoke_checked @ dotnet.wasm:1
mono_runtime_try_invoke_array @ dotnet.wasm:1
ves_icall_InternalInvoke @ dotnet.wasm:1
ves_icall_InternalInvoke_raw @ dotnet.wasm:1
do_icall @ dotnet.wasm:1
do_icall_wrapper @ dotnet.wasm:1
interp_exec_method @ dotnet.wasm:1
interp_runtime_invoke @ dotnet.wasm:1
mono_jit_runtime_invoke @ dotnet.wasm:1
do_runtime_invoke @ dotnet.wasm:1
mono_runtime_try_invoke @ dotnet.wasm:1
mono_runtime_invoke @ dotnet.wasm:1
mono_wasm_invoke_method @ dotnet.wasm:1
Module._mono_wasm_invoke_method @ dotnet.5.0.0-preview.8.20407.11.js:1
call_method @ dotnet.5.0.0-preview.8.20407.11.js:1
(anonymous) @ dotnet.5.0.0-preview.8.20407.11.js:1
callEntryPoint @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
i @ blazor.webassembly.js:1
Promise.then (async)
u @ blazor.webassembly.js:1
i @ blazor.webassembly.js:1
Promise.then (async)
u @ blazor.webassembly.js:1
i @ blazor.webassembly.js:1
Promise.then (async)
u @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
r @ blazor.webassembly.js:1
v @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
n @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1

ConfigureAwait(false) in Effect results in exception

When implementing an effect, if you return from a sub-task with ConfigureAwait(false), you will be greeted with a lovely exception.

The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.

   at Microsoft.AspNetCore.Components.Dispatcher.AssertAccess()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment)
   at Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
   at Fluxor.Blazor.Web.Components.FluxorComponent.<OnInitialized>b__3_0(IState _)
   at Fluxor.Blazor.Web.Components.StateSubscriber.<>c__DisplayClass2_1.<Subscribe>b__1(Object s, EventArgs a)
   at Fluxor.Feature`1.TriggerStateChangedCallbacks(TState newState)
   at Fluxor.Feature`1.set_State(TState value)
   at Fluxor.Store.DequeueActions()
   at Fluxor.Store.Dispatch(Object action)
   at ....my-project..../GlobalStore.cs:line 62

Simple Example:

                [EffectMethod]
                protected async Task HandleEffect(LoadAllTaskSettingsAction action, IDispatcher dispatcher)
                {
                    try
                    {
                        dispatcher.Dispatch(new Update("Handling effect for LoadAllTaskSettingsAction"));

                        dispatcher.Dispatch(new Success(await _settings.GetAllSettingsAsync().ConfigureAwait(false)));
                    }
                    catch (Exception ex)
                    {
                        dispatcher.Dispatch(new Failure(ex));
                    }
                }

[blazor] StoreInitializedEffect

Hi,

I would like to initialize some of my libraries in store initialization (or maybe I should use other place?), but this code is never run:

  public class StoreInitializedEffect : Effect<StoreInitializedAction>
    {
        private readonly HttpClient HttpClient;

        public StoreInitializedEffect(HttpClient httpClient)
        {
            HttpClient = httpClient;
        }

        protected override Task HandleAsync(StoreInitializedAction action, IDispatcher dispatcher)
        {
            dispatcher.Dispatch(new LanguagesFetchDataStoreAction());
            return Task.CompletedTask;
        }

    }

ps. I love this library, but I had to write a lot of classes for CRUDs operations

Allow action subscription code to unsubscribe

When a component has subscribed to receive notifications of when specific actions are dispatched (IActionSubscriber or FluxorComponent.SubscribeToAction it is not possible to unsubscribe from all actions within the code that is called back.

Random InvalidOperationException from DisposableCallback

Unfortunately, I don't have a lot of information available here, as the exception isn't really all that useful. At random times, we will receive an InvalidOperationException after executing an effect multiple times. It seems as though it's after the 2nd, 3rd, or 4th invocation of the same effect. (NOTE: the effect makes a couple of database calls, so everything is async using the new ConfigureAwait(false) fix)

I'm trying to come up with a reproduction case, and will update accordingly when I have a simplified version of one.

Exception Details:

System.InvalidOperationException
  HResult=0x80131509
  Message=DisposableCallback was not disposed
  Source=Fluxor
  StackTrace:
   at Fluxor.DisposableCallback.Finalize()

Using Blazor Web (Server) and the 3.1.1 preview build.

Any way to make an action update part of the state, without changing all values in the state?

Use case is that I have two booleans in my State, and I want to change one of them from true to false without changing the other (it should remember its previous value).

Problem is using the Reducers as explained in the docs one has to make a new state for every action, which forces me to set both booleans anew, so stakeholderExists will always be false after dispatching ReduceSetIsCreatableAction:

[ReducerMethod]
public static StakeholderState ReduceSetIsCreatableAction(StakeholderState state, SetIsCreatableAction action) =>
            new StakeholderState(isCreatable: action.IsCreatable, stakeholderExists: false);

Is there any way I can change individual values and set the rest of the values from the previous state?

Render before StateChanged

I would like to copy something from state to a local property so I can bind to it without modifying state directly. A later event will send the local copy back to state via an action.

If I use IState.StateChanged to do this, I sometimes get a render before the StateChanged event is fired. This makes mixing state with local properties problematic as it can produce scenarios not covered by tests.

For example, in the page below, the last paragraph should never show, but occasionally does.

@page "/customers/{id:int}"
@using Fluxor
@using FluxorGap.Data
@using FluxorGap.Store.EditCustomer
@inherits Fluxor.Blazor.Web.Components.FluxorComponent

@if (State.Value.IsLoading) {
    <p><em>Loading...</em></p>
}
else if (Customer != null) {
    <p>Customer form here</p>
}
else {
    <p style="color: red;"><strong>THIS SHOULD NEVER SHOW</strong></p>
}

@code {
    [Parameter]
    public int Id { get; set; }

    [Inject]
    private IState<State> State { get; set; }

    [Inject]
    private IDispatcher Dispatcher { get; set; }

    private Customer Customer { get; set; }

    protected override void OnInitialized()
    {
        base.OnInitialized();

        State.StateChanged += StateOnStateChanged;

        Dispatcher.Dispatch(new GetCustomerAction(Id));
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
            State.StateChanged -= StateOnStateChanged;
        
        base.Dispose(disposing);
    }

    private void StateOnStateChanged(object sender, State state)
    {
        Customer = state.Customer?.Clone();
        StateHasChanged();
    }
}

Is there another way to copy state immediately after an effect?

fluxor-gap.zip

Inheriting fluxorcomponent

Loving the library, good work.
This is probably PEBKAC but if you don't ask you don't know.

My parent component 'A', currently inherits my base component 'B'. I tried updating my base component 'B' to derive from your Fluxorcomponent but sadly It seems I have to directly inherit your Fluxorcomponent in my main component 'A', otherwise, nothing refreshes when the state changes. Why is this?

Do you have any examples of implementing when I can't inherit your FluxorComponent.

RFC: Add ability for consumers to be notified of dispatched actions

Some actions contain information that isn't destined for the store's state. For example, an effect that calls an API to return an editable object (e.g. Customer).

As the object is mutable it should not go into state where it can be modified. Instead, allow consumers to subscribe to the dispatching of actions so they can obtain a reference to the editable object for editing without it having to be reduced into state.

An example for observing dispatched actions in a component would look something like this

public class MyComponent : ComponentBase, IDisposable
{
	[Inject]
	protected IDispatcherObserver DispatcherObserver { get; set; }

	private IDisposable Subscription;

	protected override void OnInitialized()
	{
		base.OnInitialized();
		Subscription = DispatcherObserver.Observe<GetForUpdateResultAction>(SetModel);
		var getSupplierAction = new GetForUpdateAction(id: SupplierId);
		Dispatcher.Dispatch(getSupplierAction);
	}

	void IDisposable .Dispose()
	{
		Subscription?.Invoke();
	}
}

Or have a base Fluxor(some name)Component

protected override void OnInitialized()
{
    base.OnInitialized();
    Observe<GetForUpdateResultAction>(SetModel);
    var getSupplierAction = new GetForUpdateAction(id: SupplierId);
    Dispatcher.Dispatch(getSupplierAction);
}

private void SetModel(GetForUpdateResultAction action)
{
    Model = action.Supplier;
    StateHasChanged();
}

How does Fluxor know which reducer to use?

Brand new Fluxor user here, so I may be missing something obvious. I've been through the first Blazor web tutorial, and I think I understand pretty much what's going on, but have one point I can't work out.

When you dispatch an action, it seems that Fluxor looks around for a reducer method that matches the state and action types. For example, in the counter example there, you dispatch an IncrementCounterAction and Fluxor looks for a reducer with a signature like this...

CounterState ReduceIncrementCounterAction(CounterState state, IncrementCounterAction action)

I understand how it knows to look for a reducer that takes the IncrementCounterAction action type, as that is what was dispatched, but how does it know to look for a reducer with a CounterState parameter? If I add another reducer with a different state type, it doesn't get called.

Please enlighten me ๐Ÿ˜Ž. Thanks

Allow [ReducerMethod] decorated members the option of not having an Action parameter

Problem

Currently, [ReducerMethod] decorated methods must have two parameters (State and Action). This lets Fluxor know which action type should trigger the method.

The problem is that if the action has no payload (and therefore isn't used within the reducer method) then the compiler will issue a warning that the parameter is not used and suggest it may be removed.

Proposal

Allow the developer to specify the action type in [ReducerMethod] so they can omit the Action parameter.

// Currently
[ReducerMethod]
public static CounterState Reduce(CounterState state, IncrementCounterAction action) =>
  new CounterState(state.Counter + 1);

// Additional supported format
[ReducerMethod(typeof(IncrementCounterAction))]
public static CounterState Reduce(CounterState state) =>
  new CounterState(state.Counter + 1);

The dispatcher.Initialized.Status is set to RanToCompletion

Hi,

I've a razor page like this

@inject IDispatcher Dispatcher

<form action="/">
	<input @bind="_email" type="text" placeholder="Enter your email">
	<input @bind="_password" type="password" placeholder="Enter your password">
	<button @onclick="OnSignIn">Sign In</button>
</form>
@code{
	public string _email {get;set;}
	public string _password {get;set;}
	public void OnSignIn ()
	{
		Dispatcher.Dispatch(new LoginAction(_email,_password));
	}
}

While debugging I realised the Dispatcher.Initialized.Status was WaitingForActivation on the init, but will turn to RanToCompletion when the OnSignIn function is fired. And on the Effect file I cannot handle an async request to the back-end as the Task is complete.

What should I do to avoid this?

state is always one step behind after dispatch.

In the following code, when i click the submit button, it toggles between 2 states:
Visible: T F F
and
Visible T T T

The initial state in the store is T F T.

This causes Links for Second and Third steps to toggle between active and inactive.

Observations:

  1. If i hit the button, nothing changes, but if i navigate away from page and come back, i see the updated state.
  2. If i stay on the page and hit the button multiple times, it toggles, but is always showing the previous state.
  3. If i refresh the site with the browser, whatever state i had is reset to the initial state.

So why am i seeing condition 1 and 2 and why does refresh lose the whole session state in item 3 above?

@using Fluxor;
@using BlazorWizard.Store;
@using Blazorise;
@Inject IState state
@page "/wizarddemo"
@Inject IDispatcher dispatcher
@inherits Fluxor.Blazor.Web.Components.FluxorComponent

<WizardStep Name="First" @bind-Enabled="@state.Value.States[0].Visible">
    <div class="row">
        <FirstStep></FirstStep>
    </div>
</WizardStep>

<WizardStep Name="Second Step" @bind-Enabled="@state.Value.States[1].Visible">
    <div class="row">
        <p>Wow, you've reached the second step!</p>
    </div>
</WizardStep>
<WizardStep Name="Final Step" @bind-Enabled="@state.Value.States[2].Visible">
    <div class="row">
        <p>The final step has been reached. Thank you \o/</p>
    </div>
</WizardStep>
Submit

@code {
Wizard TheWizard { get; set; }

void OnSubmit()
{
    if (state.Value.States[1].Visible == false)
    {
        dispatcher.Dispatch(new BlazorWizard.Store.Wizard.WizardAllOnAction());
        System.Diagnostics.Debug.WriteLine("All On");
    }
    else
    {
        dispatcher.Dispatch(new BlazorWizard.Store.Wizard.WizardFirstOnAction());
        System.Diagnostics.Debug.WriteLine("First ON");
    }
    StateHasChanged();
    ShowStates();
}

protected override void OnInitialized()
{


    //   dispatcher.Dispatch(new BlazorWizard.Store.Wizard.WizardFirstOnAction());
    // System.Diagnostics.Debug.WriteLine("First on Init");
    //StateHasChanged();
    base.OnInitialized();
}
protected override void OnParametersSet()
{
    //state.StateChanged += (o, ws) =>
    //{
    //    StateHasChanged();
    //};
    base.OnParametersSet();

}
void ShowStates()
{
    System.Diagnostics.Debug.WriteLine("States");
    foreach (var item in state.Value.States)
    {
        System.Diagnostics.Debug.WriteLine(item.Visible);
    }
}

}

Incorrect code in the State, Actions, and Reducers tutorial

Just going through the tutorials, and have noticed what seems to be a mistake.

In the Tips section of Fluxor/Tutorials/02-Blazor/02A-StateActionsReducersTutorial, there are four methods that look like this...

[ReducerMethod]
public static SomeState(SomeState state, SomeAction action) => new SomeState();

Shouldn't these be more like this...

[ReducerMethod]
public static SomeState DoSomething(SomeState state, SomeAction action) => new SomeState();

The code as shown doesn't compile, unless I've missed something obvious (quite possible at this time of night!)

The same applies in the 01 tutorials section.

Slow ScanAssemblies in large CSB projects

Hello.
Recently I wanted to try out using Fluxor.Blazor.Web v3.1.1 in a CSB project that I am currently developing. When I added builder.Services.AddFluxor(o => o.ScanAssemblies(typeof(Program.Assembly)); it turned out that the the application started about 2 minutes ...
When I added references to Fluxor.Blazor.Web.csproj / Fluxor.csproj to my project instead of nuget package and when I added simple loging, it turned out that e.g. in ReducerMethodsDiscovery.DiscoverReducerMethods parameter allCandidateTypes contained 2100 elements and the expression:
allCandidateTypes.SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) returned 27760 elements.
Perhaps this is due to the fact that there are many components in the project, which additionally often are based on some abstract class with many methods.
When I added the logging of the results of the mentioned expression, it turned out that (if I'm not mistaken):

  • over 12000x there are methods with DeclaringType == Object (e.g. Name == "GetType" or "GetHashCode", etc.)
  • over 3000x there are methods with DeclaringType == ComponentBase
  • more than 1000x there are methods with DeclaringType == MyComponentBase
  • The method named OnInitializedAsync was around 400.
    The unique number of the methods (DeclaringType.FullName + Name) in my case was around 10000.

The execution time of the AddFluxor() method was reduced to approx. 10 seconds, when e.g. in https://github.com/mrpmorris/Fluxor/blob/3.1.1/Source/Fluxor/DependencyInjection/DependencyScanner.cs to local IEnumerable variables definition I added .ToList() at the end.

On a smaller scale, the problem can be reproduced, e.g. by cloning the repository https://github.com/SamProf/MatBlazor and adding the Fluxor in MatBlazor.Demo.ClientApp project:
builder.Services.AddFluxor (o => o.ScanAssemblies (typeof (MatBlazor.Demo.Components.BaseDocComponent) .Assembly));

  • this takes about 10seconds...

Can assembly scanning be improved somehow?

Can't get ReduxDevTools to work

Hi Peter,

If I enable options.UseReduxDevTools() I get the following error in the console.
I tried to debug without success. Am I missing something?

BTW, I find your API a lot more friendly than Redux.Net.

Thank you

Unhandled exception rendering component: Could not find '__FluxorDevTools__' in 'window'.

at System.Threading.Tasks.ValueTask`1[TResult].get_Result () <0x33ff8f8 + 0x00034> in <filename unknown>:0 
  at Fluxor.Blazor.Web.ReduxDevTools.ReduxDevToolsInterop.InitializeAsync (System.Collections.Generic.IDictionary`2[TKey,TValue] state) <0x2ee1208 + 0x000fc> in <filename unknown>:0 
  at Fluxor.Blazor.Web.ReduxDevTools.ReduxDevToolsMiddleware.InitializeAsync (Fluxor.IStore store) <0x2eca2f0 + 0x000e4> in <filename unknown>:0 
  at Fluxor.Store.InitializeMiddlewaresAsync () <0x2ec21e0 + 0x000f2> in <filename unknown>:0 
  at Fluxor.Store.ActivateStoreAsync () <0x2ec1648 + 0x000c4> in <filename unknown>:0 
  at Fluxor.Store.InitializeAsync () <0x2ec1000 + 0x000c4> in <filename unknown>:0 

I encounter error when adding NuGet to VS2019 v.16.6.0 preview 3

I encounter error when adding NuGet to VS2019 v.16.6.0 preview 3 as following (yellow warning in top of VS). Details give the following stacktrace:
StreamJsonRpc.RemoteInvocationException : Specified sequence has duplicate items
Parameter name: analyzerReferences[1]
at async StreamJsonRpc.JsonRpc.InvokeCoreAsyncTResult
at async Microsoft.CodeAnalysis.Remote.RemoteEndPoint.InvokeAsyncT
at Microsoft.VisualStudio.Telemetry.WindowsErrorReporting.WatsonReport.GetClrWatsonExceptionInfo(Exception exceptionObject)
---> (Remote Exception) {
"type": "System.ArgumentException",
"message": "Specified sequence has duplicate items
Parameter name: analyzerReferences[1]",
"stack": " at Microsoft.CodeAnalysis.PublicContract.ThrowArgumentItemNullOrDuplicateException[T](IEnumerable1 sequence, String argumentName) at Microsoft.CodeAnalysis.Solution.WithProjectAnalyzerReferences(ProjectId projectId, IEnumerable1 analyzerReferences)
at Microsoft.CodeAnalysis.Project.WithAnalyzerReferences(IEnumerable1 analyzerReferencs) at Microsoft.CodeAnalysis.Remote.SolutionCreator.<UpdateProjectAsync>d__9.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.CodeAnalysis.Remote.SolutionCreator.<UpdateProjectsAsync>d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.CodeAnalysis.Remote.SolutionCreator.<UpdateProjectsAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.CodeAnalysis.Remote.SolutionCreator.<CreateSolutionAsync>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.VisualStudio.Telemetry.WindowsErrorReporting.WatsonReport.GetClrWatsonExceptionInfo(Exception exceptionObject) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.CodeAnalysis.Remote.SolutionService.<CreateSolution_NoLockAsync>d__13.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.CodeAnalysis.Remote.SolutionService.<GetSolutionAsync>d__12.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.CodeAnalysis.Remote.CodeAnalysisService.<>c__DisplayClass17_0.<<GetSemanticClassificationsAsync>b__0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.CodeAnalysis.Remote.ServiceBase.<RunServiceAsync>d__131.MoveNext()",
"code": -2147024809,
"inner": null
} <---

Thread lock

I made a simple search box that searches trough a list of some items. This code runs fairly fast (~1-2ms).
I added some console output to verify this, those outputs are shown in the chrome console instantly as I type.

And while the console instantly reflects what I type in the UI remains locked up and lags behind severely.
To make sure I removed all logic from my reducers and just returned the old state. This resulted in reducers that took less than a ms. However the result is the same.

Am I doing something wrong or is this a limit of the Fluxor framework?

private void OnSearchTextChanged(ChangeEventArgs e)
        {
            Dispatcher.Dispatch(new SearchInDossierListAction(e.Value.ToString()));
        }

System.InvalidOperationException error

Hi,

I was able to get this up and running and everything works like charm, but passed some random time debugging my app, I'm getting an System.InvalidOperationException error and then it closes my debug session.

This is what I'm getting from the output:
An unhandled exception of type 'System.InvalidOperationException' occurred in Fluxor.dll
DisposableCallback with Id "StateSubscriber.Subscribe" was not disposed.

Do you have any idea what could I be doing wrong?

Thanks!

PS: awesome library!

Garbage Collection and pefrormance

I am using Fluxor.Blazor.Web 3.1.0 in my client-side Blazor application.
I created state, feature, action, effect and reducer to fetch data from API.
Everythink works fine, but I noticed some messages related with GC in browser console and performance problem - my api call takes 5 seconds. But in network tab in browser I can see that API call took 25ms an size is 60kB.

message in browser console:
L: GC_MAJOR_SWEEP: major size: 18896K in use: 29384K blazor.webassembly.js:1 L: GC_MAJOR: (LOS overflow) time 38.93ms, stw 38.94ms los size: 25520K in use: 17984K

so I tried to investigate the problem. In first glance I thougth that it is a problem with HttpClient, so I added Stopwatch to measure API call time.
Stopwatch stopWatch = new Stopwatch(); Console.WriteLine("fetch start " + url); stopWatch.Start(); var content = await _httpClient.GetStringAsync(url); Console.WriteLine("get in seconds: " + stopWatch.Elapsed.Seconds);
StopWatch shows 5 second per request and GC message was displayed in console.
So I tryied to do the same in empty application - without dependenceies, just single view and everythink was fine - API call took less than 0 seconds and there was no messages in console. In next steps I tryied to simplyfy my application to find the source of problem. After a few iterations of commenting and uncommenting code I relaized that problem is with State.

When State is created first time in reducer everythink is fine - data is displayed in UI very fast without problems. But when eg. user navigates to other page and after that goes back to first one, component dispathes Action again to fetch fresh data from API and this is fine. But in reducer new State object is created, old one is probably repleaced and this generates the performance problem and GC message in console. When I replaced "return line" in code below with "return new ActiveOrdersState(state.data)" each API call is fast and I do not have GC messages in console, but UI is not updated because State was not changed.

public class GetForecastDataSuccessActionReducer : Reducer<ActiveOrdersState, FetchActiveOrdersResultAction> { public override ActiveOrdersState Reduce(ActiveOrdersState state, FetchActiveOrdersResultAction action) { var data = action.Data; return new ActiveOrdersState(data); } }

I am not sure if it is an issue, but I have problem like that, I read documentation twice and looks like I did everything correctly. Do you know how to fix that?

LayoutsComponentsBase

Hi!

Great job with Fluxor!

I'm playing around with Blazor WASM 3.2.0 rev2 and found out something that might be an issue or my misunderstanding.

Problem

I've created couple of FluxorComponents. Everything works very well. But when I've placed one in MainLayout.razor its not refreshing itself after action dispatched form OnInitialized (Async too). I've moved it to Index.razor and inherited from FluxorComponent and it works again. Maybe base class for layouts could help?

Best regards
MR

Dispatching actions from Devtools does not work

Should it be possible to dispatch actions from the DevTools? I cannot get it to work, but is that expected?

I have followed the tutorial, so I have the IncrementCounterAction wired up, but nothing I have entered on the dispatcher tab has any effect when I click the dispatch button. I don't even get any error messages.

Is this a bug or just missing documentation?

Unit Test Help

I'm trying to write a component unit test. I've managed to inject Fluxor parts into my testhost but the events never seem to fire. Is there a sample unit test anywhere?

Community

My feeling is that Fluxor is on track to become an important library in the world of modern .Net development. While interest in this repository seems relatively low (based on stars/watchers), I believe this will increase as related technologies (particularly Blazor) gain adoption, mainly due to a few key advantages Fluxor has over similar libraries and homemade state management patterns.

Knowing this, it seems that some kind of community -- even just a Gitter channel -- would be hugely beneficial as this progression plays out. Fluxor provides the developer with significant flexibility. I'd like to see how others are taking advantage of this, and be able to provide my own insight to other developers based on my experience with Fluxor.

Neither StackOverflow nor this GitHub "issues" page seem to be the most effective way to communicate with other developers using Fluxor. Please consider establishing some kind of online community to facilitate the growth of this important technology.

Improve information in IDisposable action

Message=DisposableCallback with Id "StateSubscriber.Subscribe" was not disposed.

It would be nice to be able to provide additional information explaining what the common causes of this error are. Perhaps add a link URL to an MD file on this repo.

Value from state is null

Hi,

I've started to use Fluxor a few days ago. I'm developing a Blazor Webassembly app. My app calls a web API with a bearer token.

I've created an AuthState class, where the accessToken is stored. I dispatch a LoginAction, call my token endpoint in the Effect class, then dispatch a LoginResultAction, and in the AuthReducer class I create the new state with the token. It works fine, I can display the token in any components, so this part is great.

What I want to achieve, is to use this token in my DelegatingHandler, so when an Http request is sent, it sets the token from the AuthState. But whatever I do, the accessToken is always null in the DelegatingHandler.

Here is my code:

public class AuthenticationHandler : DelegatingHandler
{
    private readonly IState<AuthState> _authState;

    public AuthenticationHandler(IState<AuthState> authState)
    {
        _authState = authState;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var accessToken = _authState.Value.AccessToken;
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        return base.SendAsync(request, cancellationToken);
    }
}

When I trying to get the AccessToken, it's value is always null. I tried registering the handler as Transient, it didn't help. (If I hardcode the token, it works fine.)

I'm new to blazor and fluxor as well, maybe I'm missing something, would be great if anyone could help me.

Dependency Injection & GetInitialState

Is it possible to inject a dependency into the initial state?

Assuming the following Feature:

public class AppFeature : Feature<AppState>
{
    private readonly IImportantDependency _importantDependency;

    public override string GetName() => "App";

    public AppFeature(IImportantDependency importantDependency)
    {
        _importantDependency = importantDependency;
    }
    protected override AppState GetInitialState()
    {
        return new AppState(_importantDependency);
    }
}

Since base class Feature<TState> calls the virtual method GetInitialState from its constructor, the GetInitialState method will get called before the derived class is fully initialized (before it's constructor is called) and thus before the IImportantDependency is resolved.

I could try to inject the IImportantDependency in : Effect<StoreInitializedAction>
and then Dispatch and action with the IImportantDependency as a constructor parameter on the action, but the Task HandleAsync(StoreInitializedAction action, IDispatcher dispatcher) gets called after the IImportantDependency is required.

Examples are useless

Examples too simple and do not show real example of usage.
Please provide more complex State, at least 3-4 properties and more actions.
From examples does not clear follows how to use your library.

Add callback on effects

Hi,

I have 3 trees and 1 paged list, the trees branches all load on demand and using the state datasource causes them to refresh, I have used an event aggregator to publish a message to tell the handler to get the list from state and use the property in the code behind to bind to the tree. I can now add nodes to this without the refresh. If you were able to subscribe to a call back on the Effect it would be a little neater.

Ian.

RoutingMiddleware causes endless redirection loops in some circumstances

RoutingMiddleware dispatches a GoAction whenever NavigationManager.LocationChanged' is triggered and the new URL doesn't match the URL in the state, An Effect will then trigger to call NavigationManager.Navigate` if the state URL and current URL are different.

This allows us to ensure navigation occurs when dispatching GoAction, and that GoAction is dispatched when non-Fluxor code calls NavigationManager.Navigate.

When using Microsoft MSAL authentication the quick changing of URLs can cause in endless redirect loop.

Is it possible to await the HandleAsync method in Effects?

I need the effect to be executed synchronously, but as HandleAsync is called by Fluxor, I am not sure If I can make it so? Is there any way to ensure an action and its effect is finished before going to the nextline where the Dispatcher is used?

Add needed base calls when using FluxorComponent

I was having some issues when disposing a Component that inherited from FluxorComponent until I realized I didn't call base.OnInitialized when overriding the method. This caused the subscription that is disposed later to be null triggering the exception. I'm creating this issue just to suggest that maybe it would be a good idea to add the remark that a call to base.OnInitialized is needed when using FluxorComponent and overriding OnInitialized.

Great work with the library.

Null Refrence When Disposing Object

Version Of Blazor

  • Blazor Server

Issue

I am currently having an issue when I try go to another route. The issue occurs weather I use an "a" tag or the navigation manager built into Blazor.
When I route I get the error :

[2020-08-18T12:48:27.447Z] Error: System.AggregateException: Exceptions were encountered while disposing components. (Object reference not set to an instance of an object.) (Object reference not set to an instance of an object.) (Object reference not set to an instance of an object.) (Object reference not set to an instance of an object.)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose(Boolean disposing)
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose()
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.TryDisposeInBatch(RenderBatchBuilder batchBuilder, Exception& exception)
   --- End of inner exception stack trace ---
 ---> (Inner Exception #1) System.NullReferenceException: Object reference not set to an instance of an object.
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose(Boolean disposing)
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose()
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.TryDisposeInBatch(RenderBatchBuilder batchBuilder, Exception& exception)<---

 ---> (Inner Exception #2) System.NullReferenceException: Object reference not set to an instance of an object.
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose(Boolean disposing)
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose()
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.TryDisposeInBatch(RenderBatchBuilder batchBuilder, Exception& exception)<---

 ---> (Inner Exception #3) System.NullReferenceException: Object reference not set to an instance of an object.
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose(Boolean disposing)
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose()
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.TryDisposeInBatch(RenderBatchBuilder batchBuilder, Exception& exception)<---

if i try to manually override dispose I get a null refrence where base.Dispose(disposed); is called:

 (Inner Exception #2) System.NullReferenceException: Object reference not set to an instance of an object.
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose(Boolean disposing)
   at EdenXRPlatform.Components.Reporting.Dashboard.Charts.Engagement.Dispose(Boolean disposed) in /home/dan/Workspace/Eden/XRPlatform/EdenXRPlatform/Components/Reporting/Dashboard/Charts/Engagement.razor.cs:line 32
   at Fluxor.Blazor.Web.Components.FluxorComponent.Dispose()
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.TryDisposeInBatch(RenderBatchBuilder batchBuilder, Exception& exception)<---

Using nested objects as a state object

Hi!

When i use complex object (instance of class A) as a state object:

public class A
{
    public List<B> B_LIST { get; set; }
}

public class B
{
    public List<C> C_LIST { get; set; }
}

public class C
{
    public string Title { get; set; }
}

i always get value List C_LIST null. Is this by design?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.