Giter Club home page Giter Club logo

ngx-redux-core's Introduction

@harmowatch/ngx-redux-core

Join the chat at https://gitter.im/harmowatch/ngx-redux-core

npm version Renovate enabled Build Status HitCount Maintainability Test Coverage

The modern Redux integration for Angular 6+

This package contains a number of features that makes working with Angular and Redux very easy and comfortable. This is achieved using decorators. For example, you can decorate any class method with @ReduxAction. Every time the method is called it will dispatch a redux action.

Main Features

TypeScript support

One big advantage of this package is the TypeScript support for reducer functions. By using this package, you'll get a compiler error, if the payload of the redux action is not compatible with the reducer.

TypeScript support


Reduced boilerplate

The decorators will save you a lot of boilerplate code, so for example you don't have to call an extra service to dispatch the redux action anymore. Also the annoying switch-cases on the action-types are replaced by the @ReduxReducer decorator:

No switch case


Refactoring support

Refactoring is improved as well, since you refer directly to the action method and not to a string. Therefore, your IDE can also modify your reducer, when the action method was renamed.


Easy to test

Matchers

There are some jasmine matchers provided by this package. This makes it easy to test whether a method triggers a redux action and if the reducer really listens to it. There is also a matcher available which will ensure that the reducer does not work on the state reference. For more information about testing and matcher installation, please see the Testing Guide.

toDispatchAction
it('will dispatch a redux action', () => {
  expect(TodoListComponent.prototype.toggleListMode).toDispatchAction();
  // or test for a specific action name
  expect(TodoListComponent.prototype.toggleListMode).toDispatchAction('toggleListMode');
});
toReduceOn
it('listens to the correct actions', () => {
  expect(TodoReducer.prototype.add).toReduceOn(TodoListComponent.prototype.add);
});
notToMutateTheGivenState
it('does not mutate the given state', () => {
  expect(TodoReducer.prototype.add).notToMutateTheGivenState(state);
});

The Select Pattern

The Select Pattern gives you a powerful tool-set at your hand, to select slices of your state. The easiest way to access a state value is the reduxSelect pipe:

<pre>{{ 'some/state/path' | reduxSelect | async | json }}</pre>

Lazy Loaded Modules

Lazy Loaded Modules are also supported. So you can only initialize the reducer and the state when the respective NgModule is loaded.


Redux DevTools Extension support

The Redux DevTools Extension is fully supported and automatically enabled if your Angular app is running in dev mode.


What is Redux?

Redux is a popular and common approach to manage an application state. The three principles of redux are:


Installation

The redux package itself is not shipped with @harmowatch/ngx-redux-core. Therefore you also have to install the redux package:

$ npm install redux @harmowatch/ngx-redux-core --save

Quickstart

1. Import the root ReduxModule:

As the first step, you need to add ReduxModule.forRoot() to the root NgModule of your application.

The static forRoot method is a convention that provides and configures services at the same time. Make sure you call this method only in your root NgModule!

Please note that Lazy loading is also supported.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReduxModule } from '@harmowatch/ngx-redux-core';

import {YourModuleStateProvider} from '...';
import {TodoListReducer} from '...';

@NgModule({
  imports: [
    BrowserModule,
    ReduxModule.forRoot({
      state: {
        provider: YourModuleStateProvider, // You'll create it in step 2
        reducers: [ TodoListReducer ], // You'll create it in step 4
      }
    }),
  ],
  providers: [
    YourModuleStateProvider // You'll create it in step 2
  ],
})
export class AppModule {}

2. Create a state provider

Now you have to create a provider for your module in order to describe and initialize the state.

import { Injectable } from '@angular/core';
import { ReduxState, ReduxStateProvider } from '@harmowatch/ngx-redux-core';

export interface YourModuleState {
  items: string[];
}

@Injectable()
@ReduxState({name: 'your-module'}) // Make sure you choose a application-wide unique name
export class YourModuleStateProvider extends ReduxStateProvider<YourModuleState> {

  getInitialState(): Promise<YourModuleState> { // You can return Observable<YourModuleState> or YourModuleState as well
    return Promise.resolve({
      items: []
    });
  }}

}

Don't forget to add the state as described in step 1

You can have just one ReduxStateProvider per NgModule. But it's possible to have a state provider for each lazy loaded module.

3. Create an action dispatcher

To initiate a state change, a redux action must be dispatched. Let's assume that there is a component called TodoListComponent that displays a button. Each time the button is clicked, the view calls the function addTodo and passes the todo, which shall be added to the list.

All you have to do is decorate the function with @ReduxAction and return the todo as a return value.

import { Component } from '@angular/core';
import { ReduxAction } from '@harmowatch/ngx-redux-core';

@Component({templateUrl: './todo-list.component.html'})
export class TodoListComponent {

  @ReduxAction()
  addTodo(label: string): string {
    return label; // your return value is the payload
  }

}

Now the following action is dispatched, every time the addTodo method was called:

{
  "type": "addTodo",
  "payload": "SampleTodo"
}

You can also create a provider to dispatch actions.

4. Create the reducer

There's one more thing you need to do. You dispatch an action, but at the moment no reducer is listening to it. In order to change this, we need to create a reducer function that can make the state change as soon as the action is fired:

import { ReduxReducer, ReduxActionWithPayload } from '@harmowatch/ngx-redux-core';

import {TodoListComponent} from '...';

export class TodoListReducer {

  @ReduxReducer(TodoListComponent.prototype.add)
  addTodo(state: TodoState, action: ReduxActionWithPayload<string>): TodoState {
    return {
      ...state,
      items: state.items.concat(action.payload),
    };
  }

}

Don't forget to add the state as described in step 1

5. Select values from the state

To select a state value, you just can use the reduxSelect pipe. But you've several options to select a state value. Please check out the Select Pattern article for more information.

<ul>
  <li *ngFor="let todo of ('items' | reduxSelect | async)">{{todo}}</li>
</ul>

Documentation

You'll find the latest docs here.


You like the project? Then please give me a Star and add you to the list of Stargazers.

ngx-redux-core's People

Contributors

angular-cli avatar gitter-badger avatar kay-schecker avatar renovate-bot avatar renovate[bot] avatar sebastiansommer avatar sonata82 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ngx-redux-core's Issues

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop renovations until it is fixed.

Configuration file: package.json
Error type: Cannot parse package.json
Message: This package.json contains invalid JSON and cannot be parsed. Please fix it, or add it to your "ignorePaths" array in your renovate config so that Renovate can continue.

[Feature] angular routing state

I'm submitting a ...

[x] feature request

That's a really awesome project!!!
The one thing I'm missing is a native support for Anguar-routing. It would be great if your library could be configurated to manage the routes in the redux app state.

Development stalled

Hey,

in case you're not intending to develop this repo any longer please consider adding a statement on the README that you would look for another maintainer...

Or archive the repo (and reflect that on npmjs.com).

I at least want to go over my repos this year as well.
The last PRs came from bot and issues weren't created for a year. That's why I'm asking.

Interface naming suggestions

First of all, great take on redux with angular!

I have some naming suggestions from browsing the repo:

  • interface ReduxModuleChildConfig is located inside file redux-child-module-config.interface.ts . "child" and "module" are switched. This is a little confusing. I don't know which variant you want but I suggest to name the file the same as the interface.
  • same for interface ReduxModuleRootConfig / redux-root-module-config.interface.ts
  • ReduxActionWithPayload is inside file redux-action.interface.ts -> same issue as the other two. In this case I suggest to name the interface ReduxAction, it's more concise.

[Feature] Shall Throw an exception if a state name is registered twice.

I'm submitting a ... (check one with "x")

[ ] bug report => check the FAQ and search github for a similar issue or PR before submitting
[ ] support request => check the FAQ and search github for a similar issue before submitting
[x] feature request

Current behavior
It will not run into an error but it's an unexpected behavior to register a state twice.

Expected/desired behavior
It shall throw an exception to warn the developer and to avoid potential side effects.

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.