Giter Club home page Giter Club logo

netrx.store's Introduction

NetRx.Store

State management for .Net projects, inspired by @ngrx/store

Build status NuGet

Core concepts

Core principles are the same as in @ngrx/store:

  • State is a single immutable data structure
  • Actions represent state changes
  • Reducers take the previous state and the next action to compute the new state
  • Effects allows to express side effects through actions (typically asynchronous operations, like reading data from file, sending HTTP-request, etc.)
  • Store holds states, their reducers and effects. It plays the role of single source of truth

Overview

State

State cannot have reference type, it should be struct and can have properties of following types: simple type (bool, int, double, string, etc), collection type from System.Collections.Immutable namespace or user defined struct.

Example:

public struct AppState
{
    public bool IsLoading { get; set; }
    public string Status { get; set; }
    public decimal Amount { get; set; }
    public UserInfo User { get; set; }
    public ImmutableList<Person> Contacts { get; set; }
}

Action

User defined actions should be inherited from Action class defined in NetRx.Store namespace.

Example:

public class RefreshStatus : NetRx.Store.Action
{
}

public class SetIsLoading : NetRx.Store.Action<bool>
{
    public SetIsLoading(bool payload) : base(payload)
    {
    }
}

Reducer

There are two options how you can define reducers for your states:

  1. You can use a pure function with the following syntax: Func<ProfileState, Action, ProfileState>.

Example:

Func<ProfileState, Action, ProfileState> reducer = (state, action) =>
{
    if (action is actions.SetEmail setEmail)
    {
        state.Email = setEmail.Payload;
        return state;
    }
    if (action is actions.SetName setName)
    {
        state.Name = setName.Payload;
        return state;
    }
    if (action is actions.AddContact addContact)
    {
        state.Contacts = state.Contacts.Add(addContact.Payload);
        return state;
    }
    if (action is actions.ClearContacts)
    {
        state.Contacts = state.Contacts.Clear();
        return state;
    }

    return state;
}
  1. You can define reducer as a class (then it needs to be inherited from NetRx.Store.Reducer<TState>). Reducer class should have a set of methods with the following syntax:

public TSate Reduce(TState state, TAction action)

Example:

public class AppReducer : Reducer<AppState>
{
    public ProfileState Reduce(ProfileState state, SetIsLoading action)
    {
        state.IsLoading = action.Payload;
        return state;
    }

    public ProfileState Reduce(ProfileState state, SetUserName action)
    {
        state.User.Name = action.Payload;
        return state;
    }

    public ProfileState Reduce(ProfileState state, AddContact action)
    {
        state.Contacts = state.Contacts.Add(action.Payload);
        return state;
    }

    public ProfileState Reduce(ProfileState state, ClearContacts action)
    {
        state.Contacts = state.Contacts.Clear();
        return state;
    }
}

Effects

User defined effects should be inherited from Effect class defined in NetRx.Effects namespace.

Example:

public class UsernameChangedEffect : Effect<SetUsername>
{
    public override async Task Invoke(SetUsername action)
    {
        await NotificationService.NotifyUserNameChange(action.Payload);
    }
}

public class LoadDataEffect : Effect<LoadData, LoadDataSuccess>
{
    public override async Task<LoadDataSuccess> Invoke(LoadData action)
    {
        var result = await DataService.Load();
        return new LoadDataSuccess(new Data
        {
            Count = result.Count,
            Category = result.Category,
            Timestamp = DateTime.UtcNow
        });
    }
}

Store

Store can be created by calling static method Store.Create(). It returns the instance of BlankStore - store that doesn't have any states, reducers or effects. To put some state and reducer into it you have to call WithState method and pass the initial state and the reducer to it.

Example:

using NetRx.Store

...

var initialAppState = new AppState
{
    IsLoading = false,
    Status = "none" 
};

var store = Store.Create()
     .WithState(initialAppState, new AppReducer())
     .WithState(new ContactState(), new ContactReducer())
     .WithState(new ProductState(), new ProductReducer());

As you can see from the example above, you can call WithState method few times one by one and you will get the store that contains all of the passed states with their reducers. After that you can subscribe to listen to the state properties changes:

store.Select<AppState, string>(state => state.Status)
     .Subscribe(value =>
     {
	     Console.WriteLine(value);
     })

To trigger state changes you can call Dispatch method on the store:

store.Dispatch(new SetIsLoading(true));
store.Dispatch(new RefreshStatus());

To register some effects in your store, you can call WithEffects method right after adding states and reducers to it:

Store.Create()
     .WithState(initialAppState, new AppReducer())
     .WithEffects(new Effect[] { new LoadDataEffect(), new UsernameChangedEffect() });

In this case passed effects will be invoked when the corresponding action will be dispatched in the store.

Examples

You can find sample projects here

netrx.store's People

Contributors

ilchenkob avatar

Watchers

James Cloos avatar Mark Chipman and sidekick Mollie avatar

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.