ngrx / store Goto Github PK
View Code? Open in Web Editor NEWRxJS powered state management for Angular applications, inspired by Redux
License: MIT License
RxJS powered state management for Angular applications, inspired by Redux
License: MIT License
In previous versions this worked fine:
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
},
map: {
'@ngrx/store': 'lib/@ngrx/store/dist/store.js'
}
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
But in the latest versions there where some changes and this doesn't work anymore.
What is the recommended way now?
Thanks!
Hi, first of all, thanks for your great work!
I want to play around with your project but unfortunately I have to use our company's private Nexus npm registry that does not support npm scoped packages. The only second source I can use would be Github but I did not manage to install your project from here using JSPM.
Would it be possible for you to host your project here in a way that makes it possible to consume via JSPM?
Hello.
Would it be hard to implement a .select like in Baobab?
Like you have a store with this state:
items: [
subitems: []
]
Then i would be able to create an observeable like this:
items: Observable<Item[]>;
constructor(private _store: Store<AppStore>)
{
// Only react to state changes on items.subitems
this.items = this._store.select('items.subitems');
}
)
Some code in the examples could be streamlined by using this trick instead of const FOO="FOO";
:
https://basarat.gitbooks.io/typescript/content/docs/tips/stringEnums.html
The angular2 dependency is currently specified as "angular2": "2.0.0-beta.7", but from looking through the code it appears to used generally stable angular2 APIs, ideas, etc.
Now that we are past the storm of angular2 dependency and typing changes, how about changing the dependency to "angular2": "^2.0.0-beta.7"? I would guess (though I have not tried at this moment) that ngrx already works correctly with beta.8.
Of course there is some risk with this, but at the moment that risk is perhaps less of a problem than the inconvenience of the nailed down specific-beta-version dependency?
so I decided to go ahead and adopt this lib for our next large project.
Do you see any issues or thinks to watch for is we will use this lib with Immutable.js?
regards
Sean
FYI this lib is mentioned here:
http://victorsavkin.com/post/137821436516/managing-state-in-angular-2-applications
NICE!!!
There's a lot of excitement around Redux and I've been trying to refactor a large application to use it with Angular2. There's also a lot of information out there right now (some of it rather confusing) on the subject.
I really like the simplicity of this and am thinking about starting with this as a way forward to implement Redux in the app.
On first glance, I thought it might be a helper for angular2 on top of Redux.
Just a suggestion: it may help to state in the README that this let's you architect your application using the Redux concepts and is independent of https://github.com/rackt/redux ?
Also a comparison between the 2 like what is missing here in comparison? (maybe nothing).
Are the goals here to be an angular2 way of implementing Redux in an application and as such, provide all the concepts the other provides so as to mirror it in a sense?
Hi,
I understand that provideStore will map each reducer name to form the global state.
But how would you add a reducer that acts on the global state ?
Rationale:
.select()
exists in Rx4, and ours uses a different interface - may be confusing / might get replaced if somebody implements select for Rx5.select()
method is basically a combination of two operators - you can use it like .map(project:fn)
with a selector function, or use it like pluck(key:string)
- pluck didn't exist when I implemented store originally but it does now.distinctUntilChanged()
internally, and i'm wondering if that's a bad idea.Would be deprecated rather than immediately removed, but I think it should be done sooner than later.
Discuss?
Dear all,
I'm writing a complicate app that
therefore a few questions arise
I have read the following excellent article and I find the solution described there to be not fully encapsulated.
any ideas/comments/links/advice will be welcomed
TIA
var x1 = this._store.select('auth').map(res => res['isAuthenticated']); // returns false
var x2 = this._store.select('auth').map(res => res['mail'] === '[email protected]'); // returns false
x1.subscribe(res => {
console.log('x1', res, x1);
});
x2.subscribe(res => {
console.log('x2', res, x2);
});
Observable
.merge(x1, x2)
.first(res => res === true, null, false)
.subscribe(
next => {
console.log(next);
},
err => {
console.log(err)
},
() => {
console.log('completed');
}
);
logs this
when I switch x1 and x2 to
var x1 = Observable.of(false);
var x2 = Observable.of(false);
it correctly logs false
, which is the third param of first()
and completes
HOWEVER, when for example this._store.select('auth').map(res => res['isAuthenticated']);
returns true, it correctly return true
and completes!!
Is it because select()
returns Subject
instead of Observable
? is it because distinctUntilChanged()
WHAT DO I DOOO
First tx for a nice project...
I am about to start a large project in Angular2 (about 6-8 months of coding) and I am debating between this lib and the "official" rackt/redux. I like this lib better because it uses Observables which is the proper way of doing things in ng2.
However I was wondering what are we gaining or loosing by chossing one lib over the other...
tx
Sean.
Thanks so much for putting this code out there. I'm just starting to work with Angular 2, and have been using Redux in an angular 1 app for a few months now with good results. I've been working hard to understand how to leverage observables and this is helping things "click" in my brain :)
Now, my question is related to an issue I have when my app is first rendered. I have a simple meal planning app I'm building, and following the design of your example app pretty closely (sans normalizr and immutable.js to keep things simple). So rather than users I have recipes, but same general structure is used.
My issue right now is my root component kicks off the loading of recipes from an API:
@Component({
selector: 'meal-planning-app',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<h3>Meal Planning</h3>
<nav>
<a [routerLink]="['Recipes']">Recipes</a>
</nav>
<router-outlet></router-outlet>
`,
providers: [RecipeService, FoodService, UomService, ROUTER_PROVIDERS],
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{ path: '/recipes/...', name: 'Recipes', component: RecipesRouter }
])
export class AppComponent implements OnInit {
constructor(
private recipeService: RecipeService,
private foodService: FoodService,
private uomService: UomService
) {}
ngOnInit() {
this.recipeService.loadRecipes();
this.foodService.loadFoods();
this.uomService.loadUoms();
}
}
The recipe router is pretty simple at the moment, and contains a single route for a recipe list container:
@Component({
template: `
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES],
providers: [RecipeService]
})
@RouteConfig([
{ path: '/', name: 'Recipes', component: RecipeListContainer, useAsDefault: true }
])
export class RecipesRouter { }
Finally here's the recipe list container class:
@Component({
selector: "recipe-list-container",
template: `
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--12-col">
<recipe-list
[recipes] = "recipeService.recipes$ | async"
[loading] = "recipeService.loading$ | async"
[foods] = "foodService.foods$ | async"
(saveRecipe)="recipeService.saveRecipe($event)"
(deleteRecipe)="recipeService.deleteRecipe($event)"
(reloadRecipes) = "recipeService.reloadRecipes()">
</recipe-list>
</div>
</div>
`,
directives: [RecipeList]
})
export class RecipeListContainer {
constructor(
private recipeService: RecipeService,
private foodService: FoodService
) { }
}
Lastly, here's my recipe service class:
@Injectable()
export class RecipeService {
// The public API for this service is a couple of observable
// streams
//
recipes$: Observable<Recipe[]>;
loading$: Observable<Boolean>;
// This is creating a new observable stream for use within this
// class only.
//
private actions$ = new BehaviorSubject<Action>({ type: null, payload: null });
constructor(
private store: Store<MealPlanningState>,
api: ApiService
) {
// subscribe to changes in the state we care about
//
const store$ = this.store.select<MealPlanningState>("mealPlanningReducer");
this.recipes$ = store$.map(data => data.recipes);
this.loading$ = store$.map(data => data.recipesLoading);
// This is creating a new observable stream from our starting
// (internal) actions stream. This is basically mapping the
// starting action into a couple because of the async api
// call required (ala, redux-promise)
//
let loadStream = this.actions$
// Filter to only the internal action we care about
//
.filter(action => action.type === LOAD_RECIPES)
//
// Mmit the "pending" action as a side effect within this observable
//
.do(() => store.dispatch({ type: LOAD_RECIPES_PENDING }))
//
// Now take the original action and use mergeMap to get the
// observable from our api representing the back-end processing
// and then map the results from that into a new action that
// contains the data returned from the API
//
.mergeMap(action => api.loadRecipes(),
(action: Action, recipes: Recipe[]) => ({ type: LOAD_RECIPES_FULFILLED, payload: recipes })
);
let saveStream = this.actions$
.filter(action => action.type === SAVE_RECIPE)
.do(() => store.dispatch({ type: SAVE_RECIPE_PENDING }))
.mergeMap(action => api.saveRecipe(action.payload as Recipe),
(action: Action, recipe: Recipe) => ({ type: SAVE_RECIPE_FULFILLED, payload: recipe })
);
let deleteStream = this.actions$
.filter(action => action.type === DELETE_RECIPE && !action.payload.deleting)
.do(action => store.dispatch({ type: DELETE_RECIPE_PENDING, payload: action.payload }))
.mergeMap(action => api.deleteRecipe(action.payload as number),
(action) => ({ type: DELETE_RECIPE_FULFILLED, payload: action.payload })
);
// Now we need to combine all these internal observers into a single
// observable (using merge), and pass each action emitted to the
// store (via its dispatch() method)
//
Observable
.merge(loadStream, saveStream, deleteStream)
.subscribe((action: Action) => store.dispatch(action));
}
loadRecipes(): void {
// Emit an event on the internal action$ stream to load the recipes
//
this.actions$.next({ type: LOAD_RECIPES });
}
reloadRecipes(): void {
this.store.dispatch({ type: LOAD_RECIPES_FULFILLED, payload: [] });
this.loadRecipes();
}
saveRecipe(recipe: Recipe) {
this.actions$.next({ type: SAVE_RECIPE, payload: recipe });
}
deleteRecipe(recipeId: number) {
this.actions$.next({ type: DELETE_RECIPE, payload: recipeId });
}
}
Now I can see that when my app launches the services do in fact load the state tree with this data, but if I load the browser at the route for the recipe list directly (e.g., myapp.com/mealplanning/recipes) the recipe list doesn't actually render them. I have to click on something in my app for it to render things, so at the moment I have a refresh button I added to click and get them to render. If I start at the top-level route for this app (e.g., myapp.com/mealplanning) and click to navigate to the recipe container route they are displayed correctly.
It's kind of like when the recipe container is created, and it subscribes to the recipe observable, it doesn't immediately get the latest value from the observable. Only when I cause an event that angular recognizes does it trigger the update and render the recipes.
I've been looking through the example code, but I can't see what might cause this to happen. I'm curious if there's anything you ran into while building this that would be helpful.
Thanks again.
The typing of this method is rather unusual. You first parameterize the type of the store, with the type of the thing you are planning to select out of it. But the actual things that comes out will depend on the string/etc. you pass to select. I know that this is approximately as things are with redux, so I'm not complaining about it, but I am wondering if there is some different way to shape this part of the API to be more nicely typesafe.
As I understand typescript is not all that popular in the react community from which redux emerged, but it is of course very popular with Angular 2, and we have found it very helpful especially as applications grow in size.
How and what is the recommended way to compose reducers with dependent state?
Problem is explained there:
https://stackoverflow.com/questions/33962774/how-to-compose-redux-reducers-with-dependent-state
Thank you!
Great library and for anyone that understand the core/concept of redux, they will understand that Rx offers that and more. My only question is, couldn't a redux store implementation using Rx have been achieved without coupling it with angular. Ex. redux isn't glued to react or any other framework. Its just a state management lib. Why not implement this the same way as another option to redux and offer specific(if any) binds to ng as an integration project just like redux offer a react integration.
I'm asking because I think there is fatigue with the whole angular/react ++ and its always great to have these libraries that focus on their core disciplines without hinging to a framework. Just a thought. Users might just assume this is just for angular which is not the case. Or is it?
The example code for the thunk middleware results in a typescript error:
(9,5): error TS2346: Supplied parameters do not match any signature of call target.
I probably didn't get the Thunk interface right. But setting parameter and output to any also doesn't work.
I would love to get this running, thanks for any help!
import {createMiddleware, Action, Dispatcher} from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
interface Thunk {(action: Action): void} // <---- what should I do here?
export const thunk = createMiddleware(function(dispatcher: Dispatcher<Action>) {
return function(all$: Observable<Action | Thunk>){
const [thunks$, actions$] = all$.partition(t => typeof t === 'function');
thunks$.forEach(thunk => thunk(action => dispatcher.dispatch(action)));
return actions$;
}
}, [Dispatcher]);
i'm trying to install via npm: 'npm install @ngrx/store' and i'm getting the error 'Invalid name: "@ngrx/store"'.
what am i doing wrong?
TODO: publish only the dist folder and copy package.json to it before publishing to simplify config
Followed #50, but now I get
ReferenceError: require is not defined
For all the js sources that use the require function.
Any tips? I never used module loading before angular2/SystemJS so I'm a bit lost.
i have a details page where i fetch the data from http.
first off, does this process look correct?
` export class MeetingDetailsContainer {
meetingDetail: any;
constructor(private meetingService: MeetingService, private store: Store<AppStore>, private routeParams: RouteParams) {
let meetingDetail = store.select('meetingDetail');
meetingDetail.subscribe(data => {
if (data)
{
this.meetingDetail = Object.assign({}, data.ViewModel);
console.log('this.meetingDetail', this.meetingDetail);
}
});
const id: string = routeParams.get('meetingId');
meetingService.getMeetingById(id);
}
}
`
i can see my this.meetingDetail in console.log but why do i need an elvis operator to see a parameter?
<header><span *ngIf="meetingDetail?.MeetingID > 0">Edit Meeting</span> <span *ngIf="meetingDetail?.MeetingID === 0">New Meeting</span></header>
also, i guess along the same lines, i get a undefined when i pass meetingDetail as a parameter to another object. does anyone know why?
<meeting-details-form-header [details]="meetingDetail"></meeting-details-form-header>
It would be great if you'd have some description on why/if using this RxJS based implementation is better suited for AngularJS 2 apps than using the standard Redux. This would be very helpful for Angular 2 & RxJS beginners like me. (Especially with the ongoing discussion about "JavaScript Fatigue")
I have successfully used Redux before with AngularJS 1 but am completely new to AngularJS2 & RxJS
Best,
Andreas
i have a ng1 app details page that looks similar to this: http://www.codecovers.eu/materialadmin/pages/contacts/add
in ng1 i'm using ui router. in my abstract route i'm resolving my http and putting my data in my routedata for all the views to share. onSave simply saves the shared routedata.
in ng2 i have something that looks like this:
`
my form-header and views within my router-outlet get the deails from the store. but how do i save?
i'm struggling architecting this with ngrx. ideas?
npm install @ngrx/[email protected]
npm ERR! Windows_NT 10.0.10586
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "@ngrx/[email protected]"
npm ERR! node v5.6.0
npm ERR! npm v3.6.0
npm ERR! code E404
npm ERR! 404 Not Found: @ngrx/store
npm ERR! 404
npm ERR! 404 '@ngrx/store' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
Where should I have to implement the business logic? Action or Reducer?
When adding ngrx to my ionic project I'm getting an unresolved module.
I'm doing a standard import with typescript
import {createStore, combineReducers, Store} from '@ngrx/store';
this is the error in my ionic console. My editor(vsc) also doesn't recognise the module. I can see the the module in node_modules.
./app/app.ts
Module build failed: Error: Cannot resolve module '@ngrx/store' in /Users/damien/Develop/ionic/text-editor/app
package json import looks like
"@ngrx/store": "github:ngrx/store",
$ node -v
v4.2.1
$ npm -v
3.7.2
Hi, I'm using these example,
How to inject SomeService into the Middleware? what is the right way?
import {bootstrap} from 'angular2/platform/browser';
import {App} from './myapp';
import {provideStore, usePreMiddleware, usePostMiddleware, Middleware} from "@ngrx/store";
import {counter} from "./counter";
import {SomeService} from "./someservice";
const actionLog : Middleware = (action, someService: SomeService) => {
someService.log("something"); /**** <--- HOW TO INJECT HERE? ***/
return action.do(val => {
console.warn('DISPATCHED ACTION: ', val)
});
};
const stateLog : Middleware = state => {
return state.do(val => {
console.info('NEW STATE: ', val)
});
};
bootstrap(App, [
provideStore({counter},{counter : 0}),
usePreMiddleware(actionLog),
usePostMiddleware(stateLog)
]);
The readme suggested installing using npm, but I cannot get my program to find store (although TS has no errors). I tried with a script tag, and then with a map statement similar to the plnkr. What am I missing?
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<!-- 2. Configure SystemJS -->
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
},
map: {
'@ngrx/store': '/node_modules/@ngrx/store/dist/store.js'
}
}
});
System.import('app/main')
.then(null, console.error.bind(console));
</script>
TODOs and counters are cool and stuff, but once this #5 is figured out, it would be worth creating some sort of real world example, similar to the one in redux - https://github.com/rackt/redux/tree/master/examples/real-world
What I find extremely common in real world is list of things with pagination, detail of a thing, editing a thing.
How about:
It should probably use the proper state structure.
I'll happily give it a try myself once the async is working.
store should ideally work as a standalone module (though DI is a pretty core part of this...) - investigate moving the angular2 imports into a root file that imports the store.ts
code.
Is there any reason you'd want to define initial state in provideStore
in bootstrap?
I mean handling the initial state in the reducer(INIT__STORE
fires, switch
in all reducers ends in default, setting the state to default parameter ).. makes more sense to me and it's the way redux is doing it as well.
I've made a fork of the the ngrx todos plunkr to demonstrate this problem:
http://plnkr.co/edit/tvEovryuTZGx57PoVbhl?p=preview
Here's a summary:
{count: number}
:export const UPDATE_COUNT = 'UPDATE_COUNT';
export const sillyCount = (state = {count: 0}, {type, payload}) => {
switch (type) {
case UPDATE_COUNT:
return {count: payload};
default:
return state;
}
}
app.ts
, I subscribe to the todos
slice of the state, and as part of the subscribe, I dispatch a new action to the sillyCount
reducer store.select('todos')
.map(todos => ({ type: TodoActions.UPDATE_COUNT, payload: todos.length}))
.subscribe(x => {
store.dispatch(x);
});
todoList.ts
I subscribe to the 'sillyCount' slice of the state, and console.log it: store.select('sillyCount')
.subscribe(x => {
console.log(`sillyCount ${JSON.stringify(x)}`)
})
Now when I add a todo, I see the following in the console window:
sillyCount {"count":1}
sillyCount {"count":0}
It seems that in the subscribe to 'sillyCount', I always get two notifications, the first is what I would expect, but the second seems to be the the previous state's value, which I would not expect.
I'm sure I'm doing something rather stupid here, but I can't for the life of my work out why I'm seeing this behaviour.
needs design
tldr; refactor guts of store to be more compatible with Redux ecosystem. carrying on from #16
Notes
store.subscribe(...)
and someActionObservable.subscribe(store)
constructor(rootReducer: RootReducerOpaqueToken, enhancers?: StoreEnhancers)
Observable.proto.let
for middleware-esque functionality?Todos:
cc @gaearon @MikeRyan52
Hi guys,
I feel stupid to ask this question but I just can't figure it out.
I've been using ngrx for a while now, version 1.2.1 and everything works beautifully. I would like to update and move to 1.3.x (tested all 3 newest versions) and it's giving me the following error:
TypeError: store_1.provideStore is not a function
This appends in my main.ts file that looks basically like this
In my index.html I have the ref to @ngrx/store like this
I see that there is no more provideStore export in the store.js file.
I load the ngrx library from the package.json within the dependencies.
Any ideas what I'm doing wrong?
Again sorry for a newbie question and thanks a lot in advance :)
I've tried to change the version numbers to beta7 and it gives the following error:
{message: "No Directive annotation found on e", stack: "Error: No Directive annotation found on e↵ at n…ularjs.org/2.0.0-beta.7/angular2.min.js:10:16821)"}
The search didnt give me any relevant results. My best guess is that I need to upgrade the ngrx/store to the latest version(1.3.2) that is beta7 compatible, is that right?
Heres the link to the changed plunker: http://plnkr.co/edit/eg44QZ90E95WX2cvIHEg?p=preview
I get an error if I want to install the package "@ngrx/store" like it is mentioned in the documentation.
I executed the following commands in an empty folder:
npm install angular2
npm install @ngrx/store
Angular has been installed fine, but when I then try to install the store I get the following error:
~/tmp/packagetest$ npm install @ngrx/store
npm WARN package.json [email protected] No repository field.
npm WARN package.json [email protected] No README data
npm http GET https://registry.npmjs.org/ngrx/store
npm http 404 https://registry.npmjs.org/ngrx/store
npm ERR! TypeError: Cannot read property 'latest' of undefined
npm ERR! at next (/usr/share/npm/lib/cache.js:687:35)
npm ERR! at /usr/share/npm/lib/cache.js:675:5
npm ERR! at saved (/usr/share/npm/node_modules/npm-registry-client/lib/get.js:142:7)
npm ERR! at /usr/lib/nodejs/graceful-fs/polyfills.js:133:7
npm ERR! at Object.oncomplete (fs.js:107:15)
npm ERR! If you need help, you may report this log at:
npm ERR! <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR! <[email protected]>
npm ERR! System Linux 4.2.0-27-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install" "@ngrx/store"
npm ERR! cwd /home/stephan/tmp/packagetest
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! type non_object_property_load
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/stephan/tmp/packagetest/npm-debug.log
npm ERR! not ok code 0
It doesn't work either when I declare the dependency (version "^1.2.1") in the package.json (incl. angular2) and then execute "npm install". I get the same error then.
I'm running NodeJS 0.10.25 with npm 1.3.10 under Ubuntu 64 14.04.4
Hi,
Thanks for creating an awesome library to help us newbeis get into good application state management. I have been looking at the Redux ecosystem and have noticed the great dev tools that they have. Is there a way to use ngRx/store with redux devtools extension for Chrome? If so could someone provide some guidance?
Kind regards
Jusef
Hi Rob,
I am currently developing an ng2 app and using Redux for state management. I am really interested in switching to ngrx/store, but a few things are still not clear to me. Forgive me if this information is already there somewhere, I've spend a while searching and can't figure it out:
How would one go about assigning a reducer to a specific portion of the state tree, as in Redux's combineReducers function?
In the examples I can find, the state tree is very simple and the reducer(s) can easily operate on the entire state tree without this being unwieldy. Of course, in a real-world app you may have a reducer that needs to operate on the state.customers.list.filter
object, and just have the filter
object passed in to the reducer as the state
arg, and have its return value written back to the correct portion of the state tree.
Thanks for any help, and kudos for pushing rxjs so hard - I am just starting to appreciate the power! 👍
What is the best practice for communicate between two different components by ngrx/store?
I could not find any articles to answer that. I would glad for an example.
Many thanks,
Hi,
at the risk of appearing an utter noob, I have been trying, unsuccessfully, to get @ngrx/store to run for over a week now. If I create a clean folder, install angular2.beta.8 (or 9) as per the Quickstart guide, install @ngrx/store from npm, setup the counter example code, and modify system.js as below, I always get a console error when trying to bootstrap the provideStore provider:
Error: TypeError: store_1.provideStore is not a function(…)
[Zone.run @ angular2-polyfills.js:1243]
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
},
map: {
'@ngrx/store': 'node_modules/@ngrx/store/dist/store.js'
}
});
npm barfs over bufferutil and utf-8-validate dependencies (Nodejs v4.4.0 and 5.8.0).
I'm really keen to get ngrx working, because I want to work with a redux approach, immutable state model and observables. (vanilla redux works fine, but only handles POJO unless you get busy with middleware).
Many thanks for any steers. Happy to provide any supporting debug info.
Either I misunderstood its purpose, or I think there's an issue with the replaceReducer
function -- specifically, that it's not undoing the connection to the prior reducer.
I first noticed the issue I'm seeing when I logged in one of my reducers and saw it had run three times... hmmm. interesting, that's the same as the number of reducers that I'd merged in via replaceReducer.
I wrote a half-baked unit test to demonstrate my expectation that if I replace the reducer, the old one wouldn't be called.
I'm pretty sure the "offending" line, or at least the instigator, is in the connect function: https://github.com/ngrx/store/blob/master/src/store-backend.ts#L28
connect(nextCallbackFn: (state: any) => void) {
this._dispatcher
.let(this._preMiddleware)
.scan((state, action) => this._reducer(state, action), this._initialState)
.let(this._postMiddleware)
.subscribe(nextCallbackFn);
If this is a bug, I think I can imagine a fix, but I'll start by pushing my test up.
I looked through the docs and issues, but didn't find this question addressed anywhere.
Hi,
I was trying to use the middleware to record what is going through the reducers but unfortunalty I am getting "action.do is not a function" error. Here my bootstrap code:
`
const actionLog : Middleware = action => {
return action.do(val => {
console.warn('DISPATCHED ACTION: ', val)
});
};
const stateLog : Middleware = state => {
return state.do(val => {
console.info('NEW STATE: ', val)
});
};
bootstrap(HPZoneApp, [
ROUTER_PROVIDERS,
//provide(ROUTER_PRIMARY_COMPONENT, {useValue: SdDisplay})
provide(LocationStrategy, {useClass: HashLocationStrategy}), //remove that once you sort out server side routing
provideStore({menuZones, currentZone}),
usePreMiddleware(actionLog),
usePostMiddleware(stateLog)
])
`
Any idea what I am doing wrong?
Cheers
Jusef
If you permit, can I just point you to my stackoverflow question and the answer I got. http://stackoverflow.com/questions/35258703/typescript-ngrx-and-default-store-values/35259282#35259282
In short, I am struggling to use nested reducers to set default values and was suggested that it is due to the lack of ?
in the definition of Reducer
To my mind it makes better design sense if the parent does not need to know the definition of the child to be able to add a new child to the global model - at least that it was what I am used to in Elm
In v1.3.1
the signature for provideStore
is
provideStore(_reducer: any, initialState?: any)
But if initialState
is not provided when calling provideStore()
my app fails. I believe it needs to be changed to:
provideStore(_reducer: any, initialState: any = {})
I would like to execute some code on a state change, after all reducers have been called. So I thought I'd specify the third argument to the subscribe method (oncomplete). But complete() is not being called from Dispatcher.dispatch(), only next(). Is there any other way to accomplish this?
Hi,
I'm try to add usePreMiddleware(actionLog) and usePostMiddleware(stateLog) to my app.
but I got this error:
ORIGINAL EXCEPTION: TypeError: action.do is not a function.
In debugger on action event I not see the do() function attach to this action.
What I need to do to apply those functions?
const actionLog : Middleware = action => {
return action.do(val => {
console.warn('DISPATCHED ACTION: ', val)
});
};
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.