NgRx #Effect vs createEffect - javascript

What is the difference between createEffect vs #Effect annotation in ngrx?
#Injectable()
export class ContactsEffects {
constructor(
private actions$: Actions,
private contactsService: ContactsService,
private contactsSocket: ContactsSocketService
) {}
destroy$ = createEffect( () => this.actions$.pipe(
ofType(remove),
pluck('id'),
switchMap( id => this.contactsService.destroy(id).pipe(
pluck('id'),
map(id => removeSuccess({id}))
))
));
#Effect()
liveCreate$ = this.contactsSocket.liveCreated$.pipe(
map(contact => createSuccess({contact}))
);
}

#ngrx/effects
createEffect for type safety
As alternative to the #Effect() decorator, NgRx 8 provides the createEffect function. The advantage of using createEffect is that it’s type-safe, if the effect does not return an Observable<Action> it will give compile errors. The option { dispatch: false } still exists for effects that don’t dispatch new Actions, adding this option also removes the restriction that an effect needs to return an Observable<Action>.
Starting from NgRx 8 by default, automatically resubscribe to the effect when this happens. This adds a safety net for where the unhappy paths were missed.
It’s possible to turn this feature off by setting resubscribeOnError to false at the effect level.
example:
login$ = createEffect(() => .....), { resubscribeOnError: false });

Related

NGRX action is dispatched but effect is not firing

I'm having an issue where my NGRX effect isn't firing. Here are my actions, reducers, effects, and component code.
Here's the snippet of code from my effects, I've replaced the actual name of entities and services with just placeholders.
// entity.effects.ts
createEntity$: Observable<Action> = this.actions$.pipe(
ofType<CreateEntity>(EntityActionTypes.CreateEntity),
map(action => {
console.log("here");
return action.payload;
}),
mergeMap(data => {
return this.service.createEntity(data).pipe(
map(data => new CreateEntitySuccess(data)),
catchError(error => of(new CreateEntityError(error)))
);
})
);
entity.actions.ts
import { Action } from "#ngrx/store";
export enum EntityActionTypes {
CreateEntity = "[Entity API] Create Entity",
CreateEntitySuccess = "[Entity] Create Entity Success",
CreateEntityError = "[Entity] Create Entity Error"
}
export class CreateEntity implements Action {
readonly type = CreateEntityActionTypes.CreateEntity;
constructor(public payload: any) {}
}
// ... CreateEntitySuccess and CreateEntityError are defined here...
export type EntityActionsUnion =
| CreateEntity
| CreateEntitySuccess
| CreateEntityError;
Essentially, I have a container that on form submit dispatches an the CreateEntity action. However, I don't see the console.log() I've written into the effect. Furthermore, I have another effect for loading making a request for all entities from a REST API on LoadEntities which is working. The effect to create a new entity however is not, I don't even think it's firing.
I am also not receiving any errors. Here is the code that dispatches my action:
import * as EntityActions from '../actions/entity.actions.ts
createBuilding() {
const data = this.form.value;
const image = this.fileUploadComponent.file;
const payload = {
data,
image
};
this.store.dispatch(new EntityActions.CreateEntity(payload));
}
I have Redux dev-tools and i see the dispatch firing and the new state of loading: true being returned. However, the effect is not firing, nor are my Success or Error dispatches for resolutions firing either. Any idea as to why this is happening?
have you decorated your effects method with #Effect()? that's what i usually miss :)

Flow: is not a polymorphic type

i just integrated flow for the first time to check my javascript sources statically.
I am struggling with a error flow finds and i am not able to solve it on my own. Its about using es6 classes and inheritance. More specific i created some react Components and they should inherit some methods.
I have a Callout Component, that represents a callout message of unspecified severity. To make things a little more simple i thought about providing a ErrorMessage Component, that inherits the Callout Component. My classes Structure looks like:
React.Component
> AbstractComponent (here i add some project-wide helpers for i18n and so on
> Callout (this represents a pretty message on the screen)
> ErrorMessage (this represents an error)
Flow tells me:
Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ src/js/Components/Generic/ErrorMessage.js:14:43
statics of Callout [1] is not a polymorphic type.
11│ icon: string
12│ };
13│
[1] 14│ export default class ErrorMessage extends Callout<Props> {
15│
16│ static get defaultProps(): Props {
17│ return {
The part Callout<Props> gets highlighted
I already define the Props Type for the Callout class, so this might be the problem but i cant solve it on my own.
A similar error is thrown a few lines below, where i try to access a parent method by addressing super.content (content is a get-method of Callout).
Thanks in advance
UPDATE: Why do i want to use class inheritance?
The inheritance Callout > ErrorMessage just exists to reduce redundant code, but its not necessary, so lets ignore this and talk about a more common case:
I want to have a class AbstractComponent to make common things in my project easier.
Some examples:
Printing of translation strings: In order to make the component multilingual, i created a utility class to generate translation strings, inside a component it works like
function render() {
return (
<div>
{new Translation(
'namespace',
'key',
[some, args],
`${some} fallback message with optional ${args}`
).toString()}
</div>
)
}
In order to use this, every component in my stack ends up with the import statement on top
import Translation from "../Core/Translation"
or in the best case
import t from "../Core/Translation"
I use webpack to build a bundle and webpack seems to blow up the compiled javascript with every import statement you use. So i figured - to reduce coding effort and bundle size - i provide a intermediate component class, that adds some utility methods like:
class AbstractComponent extends React.Component {
constructor(props) {
super(props);
this.logger = props.logger || new Logger();
this.api: ApiInterface = props.api || new MockApi();
}
translate(namespace: string, key: string, args: ?[] = null, fallback: ?string): string {
return new Translation(namespace, key, args, fallback).toString();
}
svgSprite(id: string, className: string = "") {
return (
<SvgSprite id={id} className={className} />
)
}
}
I also added some other things to show you more reason for a intermediate Component class.
So, all of this works! But flow complains about missing return types and so on, thats good with me, for that purpose i want to use flow! The problem i cant solve is the inheritance itself... But for me it does make a lot of sense.
If you really want to deal with inheritance (which I don't have an issue with, I just feel like you will probably run into issues later), you can do something like the following:
class AbstractComponent<Props: {}, State: ?{} = null> extends React.Component<Props, State> {
api: ApiInterface
logger: typeof Logger
constructor(props) {
super(props);
this.logger = props.logger || new Logger();
this.api = props.api || new MockApi();
}
translate(namespace: string, key: string, args: ?string[] = null, fallback: ?string): string {
return new Translation(namespace, key, args, fallback).toString();
}
svgSprite(id: string, className: string = "") {
return (
<SvgSprite id={id} className={className} />
)
}
}
And use it like:
class Test extends AbstractComponent<{ some: string, args: string }> {
render() {
const { some, args } = this.props
return (
<div>
{this.translate(
'namespace',
'key',
[some, args],
`${some} fallback message with optional ${args}`
)}
</div>
)
}
}
Now, I will say that to some extent I understand where Facebook is coming from. Your component in this case is really already an abstract construct. And if you want this to be more flexible (let's say you have a stateless component that could benefit from having a logger and a translate function), you could do one of two things:
This is the defined type and translate function I'm using in both:
type CommonProps = {
logger?: Logger,
api?: ApiInterface,
translate?: (namespace: string, key: string, args: ?string[], fallback: ?string) => string
}
// This should look familiar
function translate(namespace: string, key: string, args: ?string[] = null, fallback: ?string): string {
return new Translation(namespace, key, args, fallback).toString();
}
Higher order component
function addCommonStuff({ logger = new Logger(), api = new MockApi(), translate = translate }: CommonProps) {
return <Props: {}>(
WrappedComponent: ComponentType<Props>
): ComponentType<
$Diff<Props, $NonMaybeType<CommonProps>>
> => (props: Props) => <WrappedComponent {...props} logger={logger} api={api} translate={translate} />
}
And used like:
class Test extends React.Component<{}> {}
const TestWithCommons = addCommonStuff({})(Test)
;<TestWithCommons />
Reusable component with a render prop
class Common extends React.Component<CommonProps & { render?: Function, children?: Function }, $NonMaybeType<CommonProps>> {
state = {
logger: this.props.logger || new Logger(),
api: this.props.api || new MockApi(),
translate: translate
}
render() {
const { children, render } = this.props
return typeof render === 'function' ? render(this.state) : (
typeof children === 'function' ? children(this.state) : null
)
}
}
And use it like this:
class TestCommon extends React.Component<{}> {
render() {
return <Common>
{({ logger, api, translate }) => translate('namespace',
'key',
null,
`Fallback message`
)}
</Common>
}
}
As an aside to this discussion, you don't need to write defaultProps as a getter for your callout. static defaultProps = {} should be enough. It shouldn't take passed in props into account or anything. If it does, you're better off using state

How to achieve a debounce service on input keyup event in angular2 with rxjs

I am trying to call to a service on input key-up event.
The HTML
<input placeholder="enter name" (keyup)='onKeyUp($event)'>
Below is the onKeyUp() function
onKeyUp(event) {
let observable = Observable.fromEvent(event.target, 'keyup')
.map(value => event.target.value)
.debounceTime(1000)
.distinctUntilChanged()
.flatMap((search) => {
// call the service
});
observable.subscribe((data) => {
// data
});
}
It was found from the network tab of the browser that, it is calling the key-up function on every key-up event(as it is supposed to do), but what I am trying to achieve is a debounce time of 1sec between each service call. Also, the event is triggered if I move the arrow key move.
plunkr link
So the chain is really correct but the problem is that you're creating an Observable and subscribe to it on every keyup event. That's why it prints the same value multiple times. There're simply multiple subscriptions which is not what you want to do.
There're obviously more ways to do it correctly, for example:
#Component({
selector: 'my-app',
template: `
<div>
<input type="text" (keyup)='keyUp.next($event)'>
</div>
`,
})
export class App implements OnDestroy {
public keyUp = new Subject<KeyboardEvent>();
private subscription: Subscription;
constructor() {
this.subscription = this.keyUp.pipe(
map(event => event.target.value),
debounceTime(1000),
distinctUntilChanged(),
mergeMap(search => of(search).pipe(
delay(500),
)),
).subscribe(console.log);
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
See your updated demo: http://plnkr.co/edit/mAMlgycTcvrYf7509DOP
Jan 2019: Updated for RxJS 6
#marlin has given a great solution and it works fine in angular 2.x but with angular 6 they have started to use rxjs 6.0 version and that has some slight different syntax so here is the updated solution.
import {Component} from '#angular/core';
import {Observable, of, Subject} from 'rxjs';
import {debounceTime, delay, distinctUntilChanged, flatMap, map, tap} from 'rxjs/operators';
#Component({
selector: 'my-app',
template: `
<div>
<input type="text" (keyup)='keyUp.next($event)'>
</div>
`,
})
export class AppComponent {
name: string;
public keyUp = new Subject<string>();
constructor() {
const subscription = this.keyUp.pipe(
map(event => event.target.value),
debounceTime(1000),
distinctUntilChanged(),
flatMap(search => of(search).pipe(delay(500)))
).subscribe(console.log);
}
}
Well, here's a basic debouncer.
ngOnInit ( ) {
let inputBox = this.myInput.nativeElement;
let displayDiv = this.myDisplay.nativeElement;
let source = Rx.Observable.fromEvent ( inputBox, 'keyup' )
.map ( ( x ) => { return x.currentTarget.value; } )
.debounce ( ( x ) => { return Rx.Observable.timer ( 1000 ); } );
source.subscribe (
( x ) => { displayDiv.innerText = x; },
( err ) => { console.error ( 'Error: %s', err ) },
() => {} );
}
}
If you set up the two indicated view children (the input and the display), you'll see the debounce work. Not sure if this doesn't do anything your does, but this basic form is (as far as I know) the straightforward way to debounce, I use this starting point quite a bit, the set of the inner text is just a sample, it could make a service call or whatever else you need it to do.
I would suggest that you check the Angular2 Tutorial that show a clean and explained example of something similar to what you're asking.
https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#observables

Angular 2 with ngrx: using selectors breaks change detection?

I'm currently building an Angular2 app using ngrx to manage state. Run into an odd problem where if I populate an observable using store.select([state]) everything seems to work fine, but if I use store.let([getState]) I can't seem to subscribe to the Observable from that point on.
I have a component:
export class Component implements OnInit {
items: Observable<Item[]>;
currentCategory: Observable<Category> = null;
constructor(
private store: Store<State>
) {
this.currentCategory = store.select(s => s.categories.selected);
// this.currentCategory = store.let(storeRoot.getSelectedCategory);
this.items = store.select(s => s.items);
}
ngOnInit() {
this.currentCategory.subscribe(cat => {
this.Items = this.store.select(s => s.items.budgetItems)
.map(items => items.filter(item => item.category === cat.name ));
});
The idea is to filter the list of items by category name when the category name changes. This works fine when I get state directly with the store.select statements, but when I try to use selectors in the store, the Observable seems to be assigned once and any changes to it no longer trigger the subscribe block.
export interface AppState {
items: fromBudgetItem.State;
categories: fromCategory.State;
};
export const composeStore = compose(storeLogger(), combineReducers)({
items: fromBudgetItem.default,
categories: fromCategory.default
});
// Categories selectors
export function getCategoriesState(state: Observable<AppState>) {
return state.select(s => s.categories);
}
export const getSelectedCategory = compose(fromCategory.getSelectedCategory, getCategoriesState);
The 'compose' statement refers to a selector in the reducer:
export interface State {
selected: null
};
export function getSelectedCategory(state$: Observable<State>) {
return state$.select(state => state.selected);
}
Any advice anyone can give? This seems to be the way they do it in the ngrx example app.

How to bind React state to RxJS observable stream?

can someone help me how to bind React State to RxJS Observable? I did sth like
componentDidMount() {
let source = Rx.Observable.of(this.state.val)
}
The ideal result is, whenever this.state.val updated (via this.setState(...)) source get updated too, so I can combine source with other RxJS observable stream.
However, in this case, source only get updated once, even after this.state.val is updated and component is re-rendered.
// Ideal result:
this.state.val = 1
source.subscribe(val => console.log(x)) //=> 1
this.state.val = 2
source.subscribe(val => console.log(val)) //=> 2
// Real result:
this.state.val = 1
source.subscribe(val => console.log(x)) //=> 1
this.state.val = 2
source.subscribe(val => console.log(val)) //=> 1 ???WTH
It might be because componentDidMount() only invoked once in React lifetime. so I move source to componentDidUpdate() which is invoked everytime after component is rendered. However, the result still remain the same.
So the question is how to make source updated whenever this.state.val updated?
Updated: Here is the solution I used to solve the prob, using Rx.Subject
// Component file
constructor() {
super(props)
this.source = new Rx.Subject()
_onChangeHandler(e) {
this.source.onNext(e.target.value)
}
componentDidMount() {
this.source.subscribe(x => console.log(x)) // x is updated
}
render() {
<input type='text' onChange={this._onChangeHandler} />
}
//
Update
To abstract out some of the below complexity, use recompose's mapPropsStream or componentFromStream. E.g.
const WithMouseMove = mapPropsStream((props$) => {
const { handler: mouseMove, stream: mouseMove$ } = createEventHandler();
const mousePosition$ = mouseMove$
.startWith({ x: 0, y: 0 })
.throttleTime(200)
.map(e => ({ x: e.clientX, y: e.clientY }));
return props$
.map(props => ({ ...props, mouseMove }))
.combineLatest(mousePosition$, (props, mousePosition) => ({ ...props, ...mousePosition }));
});
const DumbComponent = ({ x, y, mouseMove }) => (
<div
onMouseMove={mouseMove}
>
<span>{x}, {y}</span>
</div>
);
const DumbComponentWithMouseMove = WithMouseMove(DumbComponent);
Original Post
For a slightly updated answer to the OP's updated answer, using rxjs5, I came up with the following:
class SomeComponent extends React.Component {
constructor(props) {
super(props);
this.mouseMove$ = new Rx.Subject();
this.mouseMove$.next = this.mouseMove$.next.bind(this.mouseMove$);
this.mouseMove$
.throttleTime(1000)
.subscribe(idx => {
console.log('throttled mouse move');
});
}
componentWillUnmount() {
this.mouseMove$.unsubscribe();
}
render() {
return (
<div
onMouseMove={this.mouseMove$.next}
/>
);
}
}
Some notable additions:
onNext() is now next()
binding the observable next method allows it to be passed directly to the mouseMove handler
streams should be unsubscribed in componentWillUnmount hook
Furthermore, the subject streams initialized in the component constructor hook can be passed as properties to 1+ child component(s), which could all push to the stream using any of the observable next/error/complete methods. Here's a jsbin example I put together demonstrating multiple event streams shared between multiple components.
Curious if anyone has ideas on how to better encapsulate this logic to simplify stuff like binding and unsubscribing.
One option could be to use Rx.Observable.ofObjectChanges > cf. https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/ofobjectchanges.md.
However :
It uses Object.observe which is not a standard feature, hence will have to be polyfilled in some browsers and is actually being removed from inclusion in ecmascript (cf. http://www.infoq.com/news/2015/11/object-observe-withdrawn). Not the choice for the future, but it is easy to use, so if it is just for your own needs, why not.
Other option is to use a subject in one of the three methods at your disposal according to your use case : shouldComponentUpdate, componentWillUpdate, componentDidUpdate. Cf. https://facebook.github.io/react/docs/component-specs.html for when each function is executed. In one of these methods, you would check if this.state.val has changed, and emits its new value on the subject if it did.
I am not a reactjs specialist, so I guess they might be other options.
Although a subject will work, I think the best practice is to avoid using a subject when you can use an observable. In this case you can use Observable.fromEvent:
class MouseOverComponent extends React.Component {
componentDidMount() {
this.mouseMove$ = Rx.Observable
.fromEvent(this.mouseDiv, "mousemove")
.throttleTime(1000)
.subscribe(() => console.log("throttled mouse move"));
}
componentWillUnmount() {
this.mouseMove$.unsubscribe();
}
render() {
return (
<div ref={(ref) => this.mouseDiv = ref}>
Move the mouse...
</div>
);
}
}
ReactDOM.render(<MouseOverComponent />, document.getElementById('app'));
Here it is on codepen....
It seems to me that there are other times when a Subject like the best choice, like when a custom React component executes a function when an event occurs.
I would highly recommend reading this blog post on streaming props to a React component using RxJS:
https://medium.com/#fahad19/using-rxjs-with-react-js-part-2-streaming-props-to-component-c7792bc1f40f
It uses FrintJS, and applies the observe higher-order component for returning the props as a stream:
import React from 'react';
import { Observable } from 'rxjs';
import { observe } from 'frint-react';
function MyComponent(props) {
return <p>Interval: {props.interval}</p>;
}
export default observe(function () {
// return an Observable emitting a props-compatible object here
return Observable.interval(1000)
.map(x => ({ interval: x }));
})(MyComponent);
You can do it using hooks.
Here is a code sample
import { Observable, Subscription } from 'rxjs';
import { useState, useEffect } from 'react';
export default function useObservable<T = number | undefined>(
observable: Observable<T | undefined>,
initialState?: T): T | undefined {
const [state, setState] = useState<T | undefined>(initialState);
useEffect(() => {
const subscription: Subscription = observable.subscribe(
(next: T | undefined) => {
setState(next);
},
error => console.log(error),
() => setState(undefined));
return () => subscription.unsubscribe();
}, [observable])
return state;
}

Categories

Resources