Stars workflow Forks License Issues Open

nuget nuget nuget

Twitter Dotnet

Discord Twitter Twitter

logo

TimeWarp.State

TimeWarp.State (previously known as Blazor-State nuget ) is a fully asynchronous state management library for Blazor applications, leveraging the MediatR pipeline to implement the Flux pattern. It handles both Reducers and Effects consistently using async Handlers, simplifying the management of asynchronous operations throughout your app.

By utilizing the MediatR pipeline, TimeWarp.State enables a flexible, middleware-driven architecture for managing state, similar to the request-processing pipeline in ASP.NET. This approach allows developers to inject custom behaviors, such as logging, validation, and caching, directly into the state management flow.

In addition to the core library, we offer TimeWarp.State.Plus, which extends the functionality with enhanced middleware, components, and tools to further streamline state management in complex Blazor applications.

Please see the GitHub Site for source and filing of issues.

Installation

dotnet add package TimeWarp.State
dotnet add package TimeWarp.State.Plus

Check out the latest NuGet packages on the TimeWarp Enterprises NuGet page.

  • TimeWarp.State nuget
  • TimeWarp.State.Plus nuget

Getting Started

I recommend the samples for step-by-step guides to building Blazor apps with TimeWarp.State.

👉 Official documentation.

logo

The TimeWarp.State Architecture

Store 1..* State

TimeWarp.State implements a single Store with a collection of States.

To access a state you can either inherit from the TimeWarpStateComponent and use

Store.GetState<YourState>()

or move the GetState functionality into your component

  protected T GetState<T>()
  {
    Type stateType = typeof(T);
    Subscriptions.Add(stateType, this);
    return Store.GetState<T>();
  }

Pipeline

TimeWarp.State utilizes the MediatR pipeline which allows for middleware integration by registering an interface with the dependency injection container 1. TimeWarp.State provides the extension method 2 , AddTimeWarpState, which registers behaviors on the pipeline.

The interfaces available to extend the Pipeline are:

  • IPipelineBehavior
  • IRequestPreProcessor
  • IRequestPostProcessor
  • IStreamPipelineBehavior

You can add functionality to the pipeline by implementing and registering one of these interfaces. See the timewarp-architecture EventStreamBehavior for an example.

Behaviors/Middleware

TimeWarp.State ships with the following default middleware.

CloneStateBehavior

To ensure your application is in a known good state the CloneStateBehavior creates a clone of the State prior to processing the Action. If any exception occurs during the processing of the Action the state is rolled back.

RenderSubscriptionsPostProcessor

When a component accesses State, a subscription is added. The RenderSubscriptionsPostProcessor will iterate over these subscriptions and re-render those components that return true for ShouldReRender. So you don't have to worry about where to call StateHasChanged and still have the ability to finely control re-rendering.

JavaScript Interop

TimeWarp.State also uses the same "Command Pattern" for JavaScript interoperability. The JavaScript creates a request and dispatches it to Blazor where it is added to the pipeline. Handlers on the Blazor side can callback to the JavaScript side if needed.

ReduxDevToolsPostProcessor

Note

Disabled by default. This should be disabled in production as it consumes significant resources.

One of the nice features of redux is the developer tools 3. This processor implements the integration of these developer tools.

Terminology

The pattern used by TimeWarp.State and MediatR has been around for many years and goes by different names. We list various related terms here and Bold indicates the term used in TimeWarp.State.

Signals/Actions/Requests/Commands/

In Redux they call them "Action".
In UML they are "Signal".
In Command Pattern they are "Command"
In MediatR they are Request In TimeWarp.State we call them Actions when they are handled on the Client and Requests if they handled on the Server.

Reducer/Handler/Executor

This is the code that processes the Request/Action and returns the Response.

In Redux they call them "Reducer". In Command Pattern we call them "Executor".
In MediatR they are Handler.
In TimeWarp.State we call them Handler.

Feature

A Feature is the collection of the code needed to implement a particular Vertical Slice of the application.

On the server side we use the same architecture, where the Features contain Endpoint, Handler, Request, Response, etc... Each endpoint maps the HTTP Request to the Request object and then sends the Request on to the mediator pipeline. The Handler acts on the Request and returns a Response.

Server side follows the Request in Response out pattern.

A Feature Folder on the client side will contain an Action and the Handler and any corresponding files needed for this feature. The Handler acts on the Action and updates the corresponding State.

Client side follows the Action in new State out pattern.

PureFunctions vs NonPureFunctions

TimeWarp.State does not distinguish between these. As they are processed via the pipeline the same. Thus, async calls to fetch data, send emails, or just update local state are implemented in the same manner. Although the developer should be aware when Handlers have side effects and if the developer chose they could mark the Requests as such. For example IActionWithSideEffect

Acknowledgements

Jimmy Bogard (MediatR). Jimmy is an amazing developer and knowledge sharer.
Through his course at 11x Engieering, his many blog posts on Los Techies and now JimmyBogard.com, I have learned a great amount.

Peter Morris and I have been friends for many years. He is an amazing developer and a person who has taught me a great deal. Not surprisingly, Pete and I think a lot alike. We both, independently, started working on our own State Management components. Although I started first. :P Pete's component attempts to solve most of the same problems. TimeWarp.State draws on the strengths of a proven async pipeline in MediatR, where as Fluxor implements its own middleware.
If TimeWarp.State does not meet your needs be sure to checkout Fluxor.

Footnotes:


  1. https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection↩

  2. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods↩

  3. https://github.com/reduxjs/redux-devtools↩

  • Edit this page
In this article
Back to top Generated by DocFX