SlideShare a Scribd company logo
1 of 117
Gerenciamento de estado
no Angular com NgRx
Loiane Groner
@loiane
github.com/loiane
loiane.com
loiane.training
Java, JavaScript/HTML5,
Sencha, Angular, Phonegap/
Ionic
Disponível (inglês) na amazon.com.br
https://novatec.com.br/livros/estruturas-de-dados-algoritmos-em-javascript/
Entender como
desenvolver projetos
reativos com Angular
Entender como
desenvolver projetos
reativos com Angular
#itsJustAngular
Programação
eativa
http://www.reactivemanifesto.org/pt-BR
Manifesto Reativo
Reagir a informações
Reagir a usuários
Reagir a erros
Reage a dados que são
transmitidos ao longo
do tempo
Extensões reativas (RxJS)
http://reactivex.io/
Objeto Promise
Iterable Observable
Síncrono Assíncrono
ValorúnicoMúltiplosvalores
Panorama da teoria da reatividade
Padrões
eativos
Gerenciar o estado e
controle de fluxo
COMPONENTE
{…}
TEMPLATE
<..>
COMPONENTE
{…}
TEMPLATE
<..>
Binding de
Propriedades
COMPONENTE
{…}
TEMPLATE
<..>
Binding de
Propriedades
Binding de
Eventos
COMPONENTE
{…}
TEMPLATE
<..>
DIRETIVAS
{..}
Binding de
Propriedades
Binding de
Eventos
COMPONENTE
{…}
TEMPLATE
<..>
DIRETIVAS
{..}
SERVIÇOS
SERVIÇO A
SERVIÇO B
Binding de
Propriedades
Binding de
Eventos
COMPONENTE
{…}
TEMPLATE
<..>
DIRETIVAS
{..}
SERVIÇOS
SERVIÇO A
SERVIÇO B MÓDULO X
MÓDULO A
MÓDULO B
Binding de
Propriedades
Binding de
Eventos
Yay! Projeto novo em Angular!
COMPONENTE
{…}
SERVIÇO
COMPONENTE
{…}
SERVIÇO
COMPONENTE
{…}
SERVIÇO
COMPONENTE
{…}
SERVIÇO
COMPONENTE
{…}
SERVIÇO
uma semana depois…
@Component({
selector: 'app-product-order',
templateUrl: './product-order.component.html',
styleUrls: ['./product-order.component.scss']
})
export class ProductOrderComponent implements OnInit {
constructor(
private router: Router,
private route: ActivatedRoute,
private location: Location,
private productService: ProductService,
private clientService: ClientService,
private addressService: AddressService,
private userRoleService: UserRoleService,
private comboboxService: ComboboxService,
private exportFileService: ExportPDFService
) {}
}
COMPONENTE
{…}
SERVIÇO
COMPONENTE
{…}
COMPONENTE
{…}
COMPONENTE
{…}
SERVIÇO
SERVIÇO SERVIÇO SERVIÇO
COMPONENTE
{…}
SERVIÇO
@Injectable()
export class AuthService {
private loggedIn = new BehaviorSubject<boolean>(false);
get isLoggedIn() {
return this.loggedIn.asObservable();
}
login(user: User){
if (valid.userName !== '' && user.password != ‘') {
this.loggedIn.next(true);
}
}
logout(){
this.loggedIn.next(false);
}
}
O maior problema no desenvolvimento e
manutenção de sistemas de software de
grande escala é a complexidade -
sistemas grandes são difíceis de
entender
Ben Moseley & Peter Marks
Out of the Tar Pit: Analysis of Software Complexity
Acreditamos que o principal contribuinte
para esta complexidade em muitos
sistemas é o gerenciamento do estado e
o fardo que isso acrescenta ao tentar
analisar e entender o sistema. Outros
contribuintes estreitamente relacionados
são o volume do código e a preocupação
com o controle de fluxo do sistema.
Ben Moseley & Peter Marks
Out of the Tar Pit: Analysis of Software Complexity
Redux é uma
biblioteca, e também é
um padrão
Redux é uma
biblioteca, e também é
um padrão reativo
sem Redux
Componente iniciando a mudança
Não reativo
Variável comum <number>
Não reativo
Estado
com Redux
Estado
Redux Store
Ação
dispatch
subscribe
Passo 1: Definir actions
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const RESET = 'RESET';
Passo 2: Definir estado inicial e reducer
export const counterReducer: ActionReducer<number> = (
state: number = 0,
action: Action
) => {
switch (action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
case RESET:
return 0;
default:
return state;
}
};
Passo 2: Definir estado inicial e reducer
export const counterReducer: ActionReducer<number> = (
state: number = 0,
action: Action
) => {
switch (action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
case RESET:
return 0;
default:
return state;
}
};
Recebe o estado inicial
Passo 2: Definir estado inicial e reducer
export const counterReducer: ActionReducer<number> = (
state: number = 0,
action: Action
) => {
switch (action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
case RESET:
return 0;
default:
return state;
}
};
Recebe o estado inicial
Recebe a ação + payload
Passo 2: Definir estado inicial e reducer
export const counterReducer: ActionReducer<number> = (
state: number = 0,
action: Action
) => {
switch (action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
case RESET:
return 0;
default:
return state;
}
};
Recebe o estado inicial
Recebe a ação + payload
Retorna novo estado
baseado na ação
reducer Novo Estado
Estado
Ação
dispatch
+
store
Flow de dados unidirecional com Redux
Reducer Store Component
Ações
subscribe
dispatch
https://github.com/ngrx
Flow de dados unidirecional com NgRx
Reducer Component
subscribe
dispatch
Store
Ações
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './reducers/counter';
@NgModule({
imports: [
StoreModule.provideStore({ counter: counterReducer })
]
})
export class AppModule { } Reducers Globais
Store API
// seleciona todo o estado
this.store.select(state => state);
// seleciona parte do estado
this.store.select(state => state.tasks);
this.store.select('tasks');
// dispara ações
this.store.dispatch({
type: 'ACTION_TYPE',
payload: {...}
});
Store API
// seleciona todo o estado
this.store.select(state => state);
// seleciona parte do estado
this.store.select(state => state.tasks);
this.store.select('tasks');
// dispara ações
this.store.dispatch({
type: 'ACTION_TYPE',
payload: {...}
});
Store API
// seleciona todo o estado
this.store.select(state => state);
// seleciona parte do estado
this.store.select(state => state.tasks);
this.store.select('tasks');
// dispara ações
this.store.dispatch({
type: 'ACTION_TYPE',
payload: {...}
});
@Component({
template: `
<div>Counter: {{ counter }}</div>
`
})
export class CounterComponent {
counter: number;
counterSub: Subscription;
ngOnInit() {
this.counterSub = Observable.interval(1000)
.startWith(0)
.subscribe(counter => (this.counter = counter));
}
ngOnDestroy() {
this.counterSub.unsubscribe();
}
}
@Component({
template: `
<div>Counter: {{ counter }}</div>
`
})
export class CounterComponent {
counter: number;
counterSub: Subscription;
ngOnInit() {
this.counterSub = Observable.interval(1000)
.startWith(0)
.subscribe(counter => (this.counter = counter));
}
ngOnDestroy() {
this.counterSub.unsubscribe();
}
}
@Component({
template: `
<div>Counter: {{ counter }}</div>
`
})
export class CounterComponent {
counter: number;
counterSub: Subscription;
ngOnInit() {
this.counterSub = Observable.interval(1000)
.startWith(0)
.subscribe(counter => (this.counter = counter));
}
ngOnDestroy() {
this.counterSub.unsubscribe();
}
}
@Component({
template: `
<div>Counter: {{ counter }}</div>
`
})
export class CounterComponent {
counter: number;
counterSub: Subscription;
ngOnInit() {
this.counterSub = Observable.interval(1000)
.startWith(0)
.subscribe(counter => (this.counter = counter));
}
ngOnDestroy() {
this.counterSub.unsubscribe();
}
}
@Component({
template: `
<div>Counter: {{ counter }}</div>
`
})
export class CounterComponent {
counter: number;
counterSub: Subscription;
ngOnInit() {
this.counterSub = Observable.interval(1000)
.startWith(0)
.subscribe(counter => (this.counter = counter));
}
ngOnDestroy() {
this.counterSub.unsubscribe();
}
}
http://tradingadvantagedaily.com/wp-content/uploads/2017/07/1c00898.jpg
@Component({
template: `Counter: {{ counter$ | async }}`
})
export class CounterComponent {
counter$: Observable<number>;
ngOnInit() {
this.counter$ = Observable.interval(1000).startWith(0);
}
}
@Component({
template: `Counter: {{ counter$ | async }}`
})
export class CounterComponent {
counter$: Observable<number>;
ngOnInit() {
this.counter$ = Observable.interval(1000).startWith(0);
}
}
@Component({
template: `Counter: {{ counter$ | async }}`
})
export class CounterComponent {
counter$: Observable<number>;
ngOnInit() {
this.counter$ = Observable.interval(1000).startWith(0);
}
}
Integrando com a Store
@Component({…})
export class CounterComponent {
counter$: Observable<number>;
constructor(private store: Store<number>) {}
ngOnInit() {
this.counter$ = this.store.select<number>('counter');
}
}
Integrando com a Store
@Component({…})
export class CounterComponent {
counter$: Observable<number>;
constructor(private store: Store<number>) {}
ngOnInit() {
this.counter$ = this.store.select<number>('counter');
}
}
(1): Declarar Observable
Integrando com a Store
@Component({…})
export class CounterComponent {
counter$: Observable<number>;
constructor(private store: Store<number>) {}
ngOnInit() {
this.counter$ = this.store.select<number>('counter');
}
}
(1): Declarar Observable
(2): Injetar Store
Integrando com a Store
@Component({…})
export class CounterComponent {
counter$: Observable<number>;
constructor(private store: Store<number>) {}
ngOnInit() {
this.counter$ = this.store.select<number>('counter');
}
} (3): Obter estado relacionado ao Component
Template
<div class="content">
<button (click)="increment()">+</button>
<button (click)="decrement()">-</button>
<button (click)="reset()">Reset Counter</button>
<h3>{{counter$ | async}}</h3>
</div>
Template
<div class="content">
<button (click)="increment()">+</button>
<button (click)="decrement()">-</button>
<button (click)="reset()">Reset Counter</button>
<h3>{{counter$ | async}}</h3>
</div>
Observable<number>
Eventos === Actions
increment() {
this.store.dispatch({ type: INCREMENT });
}
decrement() {
this.store.dispatch({ type: DECREMENT });
}
reset() {
this.store.dispatch({ type: RESET });
}
CRUD com Ajax
Definir ações
export enum TaskActions {
LOAD = '[Task] LOAD Requested',
LOAD_SUCCESS = '[Task] LOAD Success',
CREATE = '[Task] CREATE Requested',
CREATE_SUCCESS = '[Task] CREATE Success',
UPDATE = '[Task] UPDATE Requested',
UPDATE_SUCCESS = '[Task] UPDATE Success',
REMOVE = '[Task] REMOVE Requested',
REMOVE_SUCCESS = '[Task] REMOVE Success',
ERROR = '[Task] Error'
}
Definir ações
Definir ações
export class LoadAction extends NgRxAction<any> {
type = TaskActions.LOAD;
}
export class LoadSuccessAction extends NgRxAction<Task[]> {
type = TaskActions.LOAD_SUCCESS;
}
No componente
No componente
Evento de pedido para carregar a informação do servidor
No componente
Evento de pedido para carregar a informação do servidor
Reducer
Reducer
NÃO mudar o estado diretamente
Estado deve ser imutável
Reducer
NÃO mudar o estado diretamente
Estado deve ser imutável
Reducer DEVE ser uma função PURA
Programação Funcional
Components: Dumb Components
<li class="collection-item">
<span [class.task-completed]="task.completed">{{ task.title }}</span>
<a class="secondary-content btn-floating"
(click)="onRemove()">
<i class="material-icons circle">delete</i>
</a>
<a class="secondary-content btn-floating"
(click)="onComplete()">
<i class="material-icons circle">done</i>
</a>
</li>
Components: Dumb Components
@Component({})
export class TaskItemComponent {
@Input() task: Task;
@Output() remove: EventEmitter<any> = new EventEmitter(false);
@Output() complete: EventEmitter<any> = new EventEmitter(false);
onRemove() {
this.remove.emit();
}
onComplete() {
this.complete.emit({
completed: !this.task.completed
});
}
}
Containers: Smart Components
<div class="row">
<div class="col s6 offset-s3 input-field">
<app-task-form (createTask)=“onCreateTask($event)">
</app-task-form>
<app-tasks-list
[tasks]="tasks$"
(remove)="onRemoveTask($event)"
(complete)="onUpdateTask($event)"
>
</app-tasks-list>
</div>
</div> Escutam os eventos dos
Componentes filhos e fazem o
dispatch
Containers: Smart Components
<div class="row">
<div class="col s6 offset-s3 input-field">
<app-task-form (createTask)=“onCreateTask($event)">
</app-task-form>
<app-tasks-list
[tasks]="tasks$"
(remove)="onRemoveTask($event)"
(complete)="onUpdateTask($event)"
>
</app-tasks-list>
</div>
</div> Escutam os eventos dos
Componentes filhos e fazem o
dispatch
Mas e a comunicação com servidor?
Redux apenas se interessa pela estado do
cliente (frontend)
Store side effects
Efeitos Colaterais
@ngrx/effects
Effects
Escuta a ação de Pedido e faz dispatch da ação de
“Completo" - que atualiza o estado
@Effect()
loadAction$ = this.actions$
.ofType<task.LoadAction>(task.TaskActions.LOAD)
.map(action => action.payload)
.switchMap(payload =>
this.api
.load()
.map(res => new task.LoadSuccessAction(res))
.catch(error => this.handleError(error))
);
😍
Service API
o Serviço da API não sabe do estado nem do redux
@Injectable()
export class TaskService {
private readonly API_TASKS_URL = `http://localhost:3001/tasks`;
constructor(private http: HttpClient) {}
load() {
return this.http.get<Task[]>(this.API_TASKS_URL);
}
create(record: Task) {
return this.http.post<Task>(this.API_TASKS_URL, record);
}
update(record: Task) {
return this.http.put<Task>(`${this.API_TASKS_URL}/${record.id}`, record);
}
remove(id: string) {
return this.http.delete<Task>(`${this.API_TASKS_URL}/${id}`);
}
}
Lazy Loading
@ngrx/platform (v4)
@NgModule({
imports: [
StoreModule.forFeature('task', taskReducer),
EffectsModule.forFeature([TaskEffects])
],
exports: [StoreModule, EffectsModule],
providers: [TaskStoreService]
})
export class TaskStoreModule {}
@NgModule({
imports: [
StoreModule.forRoot(reducers),
EffectsModule.forRoot([]),
StoreRouterConnectingModule,
!environment.production ? StoreDevtoolsModule.instrument({ maxAge: 50 }) : []
],
exports: [StoreModule]
})
export class AppStoreModule { }
@ngrx/platform (v4)
@NgModule({
imports: [
StoreModule.forFeature('task', taskReducer),
EffectsModule.forFeature([TaskEffects])
],
exports: [StoreModule, EffectsModule],
providers: [TaskStoreService]
})
export class TaskStoreModule {}
@NgModule({
imports: [
StoreModule.forRoot(reducers),
EffectsModule.forRoot([]),
StoreRouterConnectingModule,
!environment.production ? StoreDevtoolsModule.instrument({ maxAge: 50 }) : []
],
exports: [StoreModule]
})
export class AppStoreModule { }
Redux DevTools
Organização do Projeto
(opinião da Loiane)
Módulo Main:
App Store
Módulo Main:
App Store
Módulo Feature:
Feature Store
Boas Práticas
Estado
Evite Arrays!
Evite Arrays!
Prefira Dicionários (Object Literals)
RxJS CombineLatest
getCurrentTaskSelected() {
return Observable.combineLatest(
this.getTasks(),
this.store.select(this.selectCurrentTaskId),
(tasks, selectedId) => selectedId.map(id => tasks[id])
);
}
NgRx v5.x
@ngrx/entity
@ngrx/entity
import { createEntityAdapter, EntityAdapter, EntityState } from '@ngrx/entity';
import { Task } from './../model/task';
export interface TaskState extends EntityState<Task> {
isLoading: boolean;
selectedTaskId: any;
error: any;
}
export const taskAdapter: EntityAdapter<Task> = createEntityAdapter<Task>({
selectId: (task: Task) => task.id,
sortComparer: false,
});
export const taskInitialState: TaskState = taskAdapter.getInitialState({
isLoading: true,
selectedTaskId: null,
error: null
});
@ngrx/entity
import { createEntityAdapter, EntityAdapter, EntityState } from '@ngrx/entity';
import { Task } from './../model/task';
export interface TaskState extends EntityState<Task> {
isLoading: boolean;
selectedTaskId: any;
error: any;
}
export const taskAdapter: EntityAdapter<Task> = createEntityAdapter<Task>({
selectId: (task: Task) => task.id,
sortComparer: false,
});
export const taskInitialState: TaskState = taskAdapter.getInitialState({
isLoading: true,
selectedTaskId: null,
error: null
});
@ngrx/entity
import { createEntityAdapter, EntityAdapter, EntityState } from '@ngrx/entity';
import { Task } from './../model/task';
export interface TaskState extends EntityState<Task> {
isLoading: boolean;
selectedTaskId: any;
error: any;
}
export const taskAdapter: EntityAdapter<Task> = createEntityAdapter<Task>({
selectId: (task: Task) => task.id,
sortComparer: false,
});
export const taskInitialState: TaskState = taskAdapter.getInitialState({
isLoading: true,
selectedTaskId: null,
error: null
});
@ngrx/entity
export interface EntityState<T> {
ids: string[];
entities: Dictionary<T>;
}
export interface EntityStateAdapter<T> {
addOne<S extends EntityState<T>>(entity: T, state: S): S;
addMany<S extends EntityState<T>>(entities: T[], state: S): S;
addAll<S extends EntityState<T>>(entities: T[], state: S): S;
removeOne<S extends EntityState<T>>(key: string, state: S): S;
removeMany<S extends EntityState<T>>(keys: string[], state: S): S;
removeAll<S extends EntityState<T>>(state: S): S;
updateOne<S extends EntityState<T>>(update: Update<T>, state: S): S;
updateMany<S extends EntityState<T>>(updates: Update<T>[], state: S): S;
}
export declare type EntitySelectors<T, V> = {
selectIds: (state: V) => string[];
selectEntities: (state: V) => Dictionary<T>;
selectAll: (state: V) => T[];
selectTotal: (state: V) => number;
};
Reducer
case TaskActions.LOAD_SUCCESS: {
return ...taskAdapter.addMany(action.payload, state);
}
case TaskActions.CREATE_SUCCESS: {
return …taskAdapter.addOne(action.payload, state);
}
case TaskActions.UPDATE_SUCCESS: {
return
...taskAdapter.updateOne(
{ id: action.payload.id, changes: action.payload },
state
);
}
case TaskActions.REMOVE_SUCCESS: {
return {
...taskAdapter.removeOne(action.payload.id, state),
error: null
};
}
👏 👏 👏
VSCode
Em breve!
Prós e Contras:
1.Fluxo unidirecional ✅
2.Debug volta ao tempo (DevTools) ✅
3.Separação do código ✅
4.Fácil debug e bug fix (1, 2, e 3) ✅
5.Mais fácil pra testar devido à funções puras ✅
6.Melhor performance (onPush) ✅
7.Serialização do estado ✅
8.Mais uma camada == mais código ⛔
https://github.com/loiane/angular-ngrx4-example
Pra estudar mais…
• https://angular.io/docs/ts/latest/guide/reactive-forms.html
• https://angular.io/docs/ts/latest/guide/server-communication.html
• https://angular.io/docs/ts/latest/guide/router.html
• https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/categories.md
• https://gist.github.com/btroncone/d6cf141d6f2c00dc6b35
• http://rxmarbles.com/
• http://reactivex.io/documentation/operators
• https://github.com/ngrx
• https://github.com/ngrx/example-app
• https://auth0.com/blog/understanding-angular-2-change-detection/
• http://blog.brecht.io/A-scalable-angular2-architecture/
• http://blog.mgechev.com/2016/04/10/scalable-javascript-single-page-app-angular2-
application-architecture/
Obrigada!
@loiane
github.com/loiane
loiane.com
loiane.training
youtube.com/loianegroner

More Related Content

What's hot

Localization and Shared Preferences in android
Localization and Shared Preferences in androidLocalization and Shared Preferences in android
Localization and Shared Preferences in androidAly Arman
 
Desvendando a linguagem JavaScript
Desvendando a linguagem JavaScriptDesvendando a linguagem JavaScript
Desvendando a linguagem JavaScriptRodrigo Branas
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJames Casey
 
Boas práticas com TDD
Boas práticas com TDD Boas práticas com TDD
Boas práticas com TDD Camilo Lopes
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design PatternsLilia Sfaxi
 
Data Persistence in Android with Room Library
Data Persistence in Android with Room LibraryData Persistence in Android with Room Library
Data Persistence in Android with Room LibraryReinvently
 
Best Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part IIIBest Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part IIIICS
 
Iterator Design Pattern
Iterator Design PatternIterator Design Pattern
Iterator Design PatternVarun Arora
 
Agile manifesto 17 authors - who made it? what do they do?
Agile manifesto 17 authors - who made it? what do they do?Agile manifesto 17 authors - who made it? what do they do?
Agile manifesto 17 authors - who made it? what do they do?Jae-Hee Lee
 
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...Doug Jones
 
State Management in Angular/React
State Management in Angular/ReactState Management in Angular/React
State Management in Angular/ReactDEV Cafe
 
Server-side JS with NodeJS
Server-side JS with NodeJSServer-side JS with NodeJS
Server-side JS with NodeJSLilia Sfaxi
 
Django Architecture Introduction
Django Architecture IntroductionDjango Architecture Introduction
Django Architecture IntroductionHaiqi Chen
 
TypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painTypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painSander Mak (@Sander_Mak)
 
Design Patterns
Design PatternsDesign Patterns
Design Patternsfrgo
 
Repository and Unit Of Work Design Patterns
Repository and Unit Of Work Design PatternsRepository and Unit Of Work Design Patterns
Repository and Unit Of Work Design PatternsHatim Hakeel
 

What's hot (20)

Ngrx slides
Ngrx slidesNgrx slides
Ngrx slides
 
Localization and Shared Preferences in android
Localization and Shared Preferences in androidLocalization and Shared Preferences in android
Localization and Shared Preferences in android
 
Desvendando a linguagem JavaScript
Desvendando a linguagem JavaScriptDesvendando a linguagem JavaScript
Desvendando a linguagem JavaScript
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Boas práticas com TDD
Boas práticas com TDD Boas práticas com TDD
Boas práticas com TDD
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 
Programando com Python
Programando com PythonProgramando com Python
Programando com Python
 
Data Persistence in Android with Room Library
Data Persistence in Android with Room LibraryData Persistence in Android with Room Library
Data Persistence in Android with Room Library
 
Best Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part IIIBest Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part III
 
Iterator Design Pattern
Iterator Design PatternIterator Design Pattern
Iterator Design Pattern
 
Agile manifesto 17 authors - who made it? what do they do?
Agile manifesto 17 authors - who made it? what do they do?Agile manifesto 17 authors - who made it? what do they do?
Agile manifesto 17 authors - who made it? what do they do?
 
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
 
State Management in Angular/React
State Management in Angular/ReactState Management in Angular/React
State Management in Angular/React
 
Ngrx: Redux in angular
Ngrx: Redux in angularNgrx: Redux in angular
Ngrx: Redux in angular
 
Server-side JS with NodeJS
Server-side JS with NodeJSServer-side JS with NodeJS
Server-side JS with NodeJS
 
Django Architecture Introduction
Django Architecture IntroductionDjango Architecture Introduction
Django Architecture Introduction
 
TypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painTypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the pain
 
Solid Principles
Solid PrinciplesSolid Principles
Solid Principles
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
Repository and Unit Of Work Design Patterns
Repository and Unit Of Work Design PatternsRepository and Unit Of Work Design Patterns
Repository and Unit Of Work Design Patterns
 

Similar to Gerenciamento de estado no Angular com NgRx

Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsEvangelia Mitsopoulou
 
N Things You Don't Want to Repeat in React Native
N Things You Don't Want to Repeat in React NativeN Things You Don't Want to Repeat in React Native
N Things You Don't Want to Repeat in React NativeAnton Kulyk
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react applicationGreg Bergé
 
React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practicesClickky
 
Evan Schultz - Angular Camp - ng2-redux
Evan Schultz - Angular Camp - ng2-reduxEvan Schultz - Angular Camp - ng2-redux
Evan Schultz - Angular Camp - ng2-reduxEvan Schultz
 
Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Nir Kaufman
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to HooksSoluto
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJSKyung Yeol Kim
 
What is new in sulu 2.0
What is new in sulu 2.0What is new in sulu 2.0
What is new in sulu 2.0danrot
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonfNataliya Patsovska
 
From zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for java scriptFrom zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for java scriptMaurice De Beijer [MVP]
 
Visualforce: Using JavaScript Remoting for Apex Controllers
Visualforce: Using JavaScript Remoting for Apex ControllersVisualforce: Using JavaScript Remoting for Apex Controllers
Visualforce: Using JavaScript Remoting for Apex Controllersprabhat gangwar
 
A Journey with React
A Journey with ReactA Journey with React
A Journey with ReactFITC
 

Similar to Gerenciamento de estado no Angular com NgRx (20)

Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applications
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
N Things You Don't Want to Repeat in React Native
N Things You Don't Want to Repeat in React NativeN Things You Don't Want to Repeat in React Native
N Things You Don't Want to Repeat in React Native
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react application
 
React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practices
 
Evan Schultz - Angular Camp - ng2-redux
Evan Schultz - Angular Camp - ng2-reduxEvan Schultz - Angular Camp - ng2-redux
Evan Schultz - Angular Camp - ng2-redux
 
Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
React hooks
React hooksReact hooks
React hooks
 
What is new in sulu 2.0
What is new in sulu 2.0What is new in sulu 2.0
What is new in sulu 2.0
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonf
 
Ngrx
NgrxNgrx
Ngrx
 
Side effects-con-redux
Side effects-con-reduxSide effects-con-redux
Side effects-con-redux
 
Understanding redux
Understanding reduxUnderstanding redux
Understanding redux
 
From zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for java scriptFrom zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for java script
 
Road to react hooks
Road to react hooksRoad to react hooks
Road to react hooks
 
Visualforce: Using JavaScript Remoting for Apex Controllers
Visualforce: Using JavaScript Remoting for Apex ControllersVisualforce: Using JavaScript Remoting for Apex Controllers
Visualforce: Using JavaScript Remoting for Apex Controllers
 
A Journey with React
A Journey with ReactA Journey with React
A Journey with React
 
Rx workshop
Rx workshopRx workshop
Rx workshop
 

Recently uploaded

Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 

Recently uploaded (20)

Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 

Gerenciamento de estado no Angular com NgRx