mrpmorris / Fluxor

Fluxor is a zero boilerplate Flux/Redux library for Microsoft .NET and Blazor.
MIT License
1.22k stars 139 forks source link

Having troubles with Fluxor in Blazor auto #499

Closed stefancata26 closed 1 week ago

stefancata26 commented 1 week ago

Description

I am experiencing difficulties integrating Fluxor into my Blazor Auto application. While the initial setup appears correct, the state management does not work as expected, particularly with action dispatching and state updates.

Projects Structure

Problem Details

State Not Updating: The counter button does not increment the count when clicked. The action seems to be placed in the queued actions but is not dequeued correctly. I tried creating a blank Blazor WASM project and Fluxor was working just fine.

Code Snippets

Counter.razor

@page "/counter"
@using Fluxor
@using Nexus.Retail.Components.State
@inject IDispatcher Dispatcher
@inject IState<CounterState> CounterState

<h3>Counter</h3>

<p role="status">Current count: @CounterState.Value.Count</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private void IncrementCount()
    {
        Dispatcher.Dispatch(new IncrementCounterAction());
    }
}

CounterState.cs

using Fluxor;

namespace Nexus.Retail.Components.State
{
    [FeatureState]
    public class CounterState
    {
        public int Count { get; }

        public CounterState() 
        {
            Count = 0; // Default value
        }

        public CounterState(int count)
        {
            Count = count;
        }
    }
}

IncrementCounterAction.cs

namespace Nexus.Retail.Components.State
{
    public class IncrementCounterAction { }
}

CounterReducers.cs

using Fluxor;

namespace Nexus.Retail.Components.State
{
    public static class CounterReducers
    {
        [ReducerMethod]
        public static CounterState ReduceIncrementCounterAction(CounterState state, IncrementCounterAction action) =>
            new CounterState(state.Count + 1);
    }
}

Program.cs (Server-Side)

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Fluxor;
using Fluxor.Blazor.Web.ReduxDevTools;
using Nexus.Retail.Components;
using Nexus.Retail.Components.Services;
using Nexus.Retail.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents().AddInteractiveServerComponents().AddInteractiveWebAssemblyComponents();
builder.Services.AddSingleton<IFormFactor, FormFactor>();
builder.Services.AddFluxor(o =>
{
    o.ScanAssemblies(typeof(Nexus.Retail.Components.State.CounterState).Assembly);
    o.UseReduxDevTools(rdt => rdt.Name = "My application");
});

builder.WebHost.UseStaticWebAssets();

var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode().AddInteractiveWebAssemblyRenderMode().AddAdditionalAssemblies(
    typeof(Nexus.Retail.Components._Imports).Assembly,
    typeof(Nexus.Retail.Client._Imports).Assembly
);
app.Run();

Program.cs (Client-Side)

using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Nexus.Retail.Components.Services;
using Fluxor;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddSingleton<IFormFactor, FormFactor>();
builder.Services.AddFluxor(o => o.ScanAssemblies(typeof(Nexus.Retail.Components.State.CounterState).Assembly));
await builder.Build().RunAsync();

App.razor (Server-Side)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="_content/Nexus.Retail.Components/bootstrap/bootstrap.min.css" />
    <link rel="stylesheet" href="_content/Nexus.Retail.Components/app.css" />
    <link rel="stylesheet" href="Nexus.Retail.styles.css" />
    <link rel="icon" type="image/png" href="_content/Nexus.Retail.Components/favicon.png" />
    <HeadOutlet @rendermode="InteractiveAuto" />
</head>

<body>
    <Fluxor.Blazor.Web.StoreInitializer />
    <Routes @rendermode="InteractiveAuto" />
    <script src="_framework/blazor.web.js"></script>
</body>

</html>

.csproj (Server-Side)

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Fluxor" Version="6.0.0" />
    <PackageReference Include="Fluxor.Blazor.Web" Version="6.0.0" />
    <PackageReference Include="Fluxor.Blazor.Web.ReduxDevTools" Version="6.0.0" />
    <ProjectReference Include="..\Nexus.Retail.Client\Nexus.Retail.Client.csproj" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.0-preview.5.24306.11" />
  </ItemGroup>

</Project>

Additional Context

Request

Any guidance on resolving these issues would be greatly appreciated. Specifically, I'm looking for:

stefancata26 commented 1 week ago

I found the solution. https://github.com/mrpmorris/Fluxor/issues/459