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

Antipatrones de desarrollo de software
Antipatrones de desarrollo de softwareAntipatrones de desarrollo de software
Antipatrones de desarrollo de softwarePablo Bouzada
 
Collections - Maps
Collections - Maps Collections - Maps
Collections - Maps Hitesh-Java
 
Cracking OCA and OCP Java 8 Exams
Cracking OCA and OCP Java 8 ExamsCracking OCA and OCP Java 8 Exams
Cracking OCA and OCP Java 8 ExamsGanesh Samarthyam
 
Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kros Huang
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.David Gómez García
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaVladimir Kostyukov
 
Angular state Management-NgRx
Angular state Management-NgRxAngular state Management-NgRx
Angular state Management-NgRxKnoldus Inc.
 
Microservice - Up to 500k CCU
Microservice - Up to 500k CCUMicroservice - Up to 500k CCU
Microservice - Up to 500k CCUViet Tran
 
3. Data types and Variables
3. Data types and Variables3. Data types and Variables
3. Data types and VariablesNilesh Dalvi
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaKros Huang
 
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로Jaeseung Ha
 
kotlinx.serialization
kotlinx.serializationkotlinx.serialization
kotlinx.serializationArawn Park
 
Workshop 22: React-Redux Middleware
Workshop 22: React-Redux MiddlewareWorkshop 22: React-Redux Middleware
Workshop 22: React-Redux MiddlewareVisual Engineering
 

What's hot (20)

Constructors and Method Overloading
Constructors and Method OverloadingConstructors and Method Overloading
Constructors and Method Overloading
 
Antipatrones de desarrollo de software
Antipatrones de desarrollo de softwareAntipatrones de desarrollo de software
Antipatrones de desarrollo de software
 
Introduction à Angular 2
Introduction à Angular 2Introduction à Angular 2
Introduction à Angular 2
 
Collections - Maps
Collections - Maps Collections - Maps
Collections - Maps
 
Cracking OCA and OCP Java 8 Exams
Cracking OCA and OCP Java 8 ExamsCracking OCA and OCP Java 8 Exams
Cracking OCA and OCP Java 8 Exams
 
Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in Scala
 
Java script
Java scriptJava script
Java script
 
Core java Essentials
Core java EssentialsCore java Essentials
Core java Essentials
 
Angular state Management-NgRx
Angular state Management-NgRxAngular state Management-NgRx
Angular state Management-NgRx
 
Microservice - Up to 500k CCU
Microservice - Up to 500k CCUMicroservice - Up to 500k CCU
Microservice - Up to 500k CCU
 
3. Data types and Variables
3. Data types and Variables3. Data types and Variables
3. Data types and Variables
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJava
 
JSpiders - Wrapper classes
JSpiders - Wrapper classesJSpiders - Wrapper classes
JSpiders - Wrapper classes
 
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
 
String Handling
String HandlingString Handling
String Handling
 
kotlinx.serialization
kotlinx.serializationkotlinx.serialization
kotlinx.serialization
 
Java String class
Java String classJava String class
Java String class
 
Workshop 22: React-Redux Middleware
Workshop 22: React-Redux MiddlewareWorkshop 22: React-Redux Middleware
Workshop 22: React-Redux Middleware
 

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
 
Ngrx slides
Ngrx slidesNgrx slides
Ngrx slides
 
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
 

Recently uploaded

Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
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
 
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
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
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
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 

Recently uploaded (20)

Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
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
 
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
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 

Gerenciamento de estado no Angular com NgRx