Fluxor-persist is a library to persist Fluxor states.
Persisting states is a pretty common task .. in react I use redux-persist so this carries over some of the same ideas. Most often I use it to ensure a user doesn't lose their state on a page refresh or when leaving or returning to a site but this library has no blazor dependencies so it can be used anywhere.
You can download the latest release / pre-release NuGet packages from the official Fluxor-persist nuget pages.
The easiest way to get started is to look at the sample blazor app here(https://github.com/Tailslide/fluxor-persist)
To add Fluxor-persist to your existing blazor fluxor application you want to:
-
Add a NuGet package reference to
Fluxor.Persist
-
Add
.UsePersist()
in Program.cs when building your existing Fluxor service withAddFluxor()
-
Make a class that implements
IStateStorage
to persist your state however you want. It just needs to be able to save and retrieve a string / string key value pair. -
Override
OnInitialized
in your MainLayout to initialize your storage:Dispatcher.Dispatch(new InitializePersistMiddlewareAction() { StorageService = new LocalStateStorage(this.localStorage), RehydrateStatesFromStorage = true });
You can detect that state has been rehydrated from storage. I use this in my MainLayout which inherits from FluxorLayout. In OnInitialized
after I intialize the middleware to detect state restore and force a refresh:
Dispatcher.Dispatch(new InitializePersistMiddlewareAction() { StorageService = new LocalStateStorage(this.localStorage), RehydrateStatesFromStorage = true });
this.SubscribeToAction<InitializePersistMiddlewareResultSuccessAction>(result =>
{
Console.WriteLine($"**** State rehydrated**");
this.StateHasChanged();// we now have state, we can re-render to reflect binding changes
});
using Blazored.LocalStorage;
using Fluxor.Persist.Storage;
using System.Threading.Tasks;
namespace Fluxor.Persist.Sample.Storage
{
public class LocalStateStorage :IStateStorage
{
private ILocalStorageService LocalStorage { get; set; }
public LocalStateStorage(ILocalStorageService localStorage)
{
LocalStorage = localStorage;
}
public async ValueTask<string> GetStateJsonAsync(string statename)
{
return await LocalStorage.GetItemAsStringAsync(statename);
}
public async ValueTask StoreStateJsonAsync(string statename, string json)
{
await LocalStorage.SetItemAsync(statename, json);
}
}
}
You can blacklist or whitelist state names to indicate if they should be persisted. Use only a blacklist or a whitelist not both. Regardless of settings, the states @routing and PersistMiddleware are never persisted.
Example: .UsePersist(x => x.StateBlackList= "mystate1,mystate2")
You can attribute your state records so that certain fields do not get serialized. To not persist a 'isloading' flag for example:
public record LoginState (
[property: JsonIgnore] bool IsLoading,
int CounterValue
)
{
[JsonConstructor]
public LoginState(int CounterValue) : this(false, CounterValue) { }
}