This release introduces the new decorator interface. You can now use
@select
to create an observable from a slice of store state.
See 'the select pattern' in README.md for a complete description of how to use this new decorator.
You no longer need to manually subscribe and ApplicationRef.tick()
for Redux DevTools to work; we do this automatically for you.
We've changed how bootstrapping Ng2-Redux works. The provider
function has gone away in favour of making NgRedux a first-class
@Injectable
.
You now configure your store in the constructor of your top-level app component instead of prior to bootstrapping. This allows the store to be configured with middleware and enhancers that rely on Angular 2 services, which previously was unnecessarily difficult.
bootstrap.ts:
import { bootstrap } from '@angular/platform-browser-dynamic';
import { createStore, applyMiddleware, compose } from 'redux';
import { NgRedux } from 'ng2-redux';
const createLogger = require('redux-logger');
const persistState = require('redux-localstorage');
import { rootReducer } from './reducers';
import { App } from './app';
// Confusing and hard to use with dependency injection.
const middleware = [ createLogger() ];
const enhancers = [ persistState('counter', { key: 'example-app' }) ];
const store = compose(
applyMiddleware(middleware),
...enhancers)
(createStore)(rootReducer);
bootstrap(App, [ provide(store) ])
app.ts
import { Component } from '@angular/core';
import { NgRedux } from 'ng2-redux';
@Component({
// ...
})
export class App {
constructor(private ngRedux: NgRedux) {}
}
bootstrap.ts:
import { bootstrap } from '@angular/platform-browser-dynamic';
import { NgRedux } from 'ng2-redux';
import { App } from './app';
bootstrap(App, [ Ng2Redux ]);
app.ts
import { Component } from '@angular/core';
import { NgRedux } from 'ng2-redux';
import { reduxLogger } from 'redux-logger';
import { initialState, rootReducer } from './reducers';
@Component({
// ...
})
export class App {
constructor(private ngRedux: NgRedux) {
const middleware = [ reduxLogger ];
const enhancers = [ persistState('counter', { key: 'example-app' }) ];
// Easier to understand, and can use middleware or enhancers from DI.
ngRedux.configureStore(rootReducer, initialState, middleware, enhancers);
}
}
The example app has been updated to use @select
and a
DI-aware action creator service (counter-actions.ts
). It now also
shows examples of using middleware and enhancers from the Redux
community: redux-logger
and redux-localstorage
.
- Type definitions:
- Ported to typescript
- Supports typed stores / reducers
- Uses offical Redux type definitions
- Type Injectable:
- Able to inject
NgRedux
into your component by type, and not need@Inject('ngRedux')
@Inject('ngRedux')
still works
- Able to inject
import { NgRedux } from 'ng2-redux';
// ...
export class MyComponent {
constructor(private ngRedux: NgRedux) {}
}
- State as Observable: Ability to expose parts of your state as an observable.
select<S>(selector: string | number | symbol | ((state: RootState) => S), comparer?: (x: any, y: any) => boolean): Observable<S>;
wrapActionCreators: (actions: any) => (dispatch: Redux.Dispatch<any>) => Redux.ActionCreator<{}> | Redux.ActionCreatorsMapObject;
Example use:
import { NgRedux } from 'ng2-redux';
// ...
export class MyComponent implements OnInit {
countByKey$: Observable<number>;
countByFunc$: Observable<number>;
constructor(private ngRedux: NgRedux) {
this.countByKey$ = this.ngRedux.select('count');
this.countByFunc$ = this.ngRedux.select(state=>state.count);
}
}
Also have the ability to provide a custom compare function.
import { is, Map } from 'immutable';
import { NgRedux } from 'ng2-redux';
// ...
export class MyComponent implements OnInit {
person$: Observable<Map<string,any>>;
constructor(private ngRedux: ngRedux) {
// even if the reference of the object has changed,
// if the data is the same - it wont be treated as a change
this.person$ = this.ngRedux.select(state=>state.people.get(0),is);
}
}