www.devcode.la
www.devcode.la
www.devcode.la
1. Comprender los conceptos claves de Redux.
2. Aprender a implementar un arquitectura de datos escalable con Angular.
3. Implementar Redux + Angular.
4. Aprender a definir estados globales para la aplicación.
www.devcode.la
1. Arquitectura escalable de datos.
2. Mayor control en el flujo de datos.
3. Programación Funcional.
4. Control de estados.
5. Estado global e immutable
www.devcode.la
Módulo 1: Introducción
Módulo 2: Ideas clave de Redux
Módulo 3: Redux + Angular
Módulo 4: Proyecto
www.devcode.la
- Conocimiento previo en Angular.
- VsCode
- Goolge Chrome
- Angular CLI
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
Controlar el estado
- Respuestas del servidor
- Datos en cache
- Datos locales
- Estados de la UI
www.devcode.la
"En cierto punto, ya no se entiende que esta pasando en la aplicación ya que perdiste control sobre el cuándo, el por qué y el cómo de su estado"
www.devcode.la
Redux intenta hacer predecibles las mutaciones del estado
- Store = La única fuente de la verdad
- Actions = El estado es de solo lectura
- Reducers = Los cambios los realizan acciones puras
www.devcode.la
www.devcode.la
RX = manejar la complejidad de aplicaciones asíncronas
www.devcode.la
www.devcode.la
{
todos: [{
text: 'Aprender redux',
completed: true
}, {
text: 'Visitar nicobytes.com',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}
www.devcode.la
{ type: 'ADD_TODO', text: 'Ir a nadar a la piscina' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
www.devcode.la
www.devcode.la
function visibilityFilter(state = 'SHOW_ALL', action) {
if (action.type === 'SET_VISIBILITY_FILTER') {
return action.filter;
} else {
return state;
}
}
www.devcode.la
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([{ text: action.text, completed: false }]);
case 'TOGGLE_TODO':
return state.map((todo, index) =>
action.index === index ?
{ text: todo.text, completed: !todo.completed } :
todo
)
default:
return state;
}
}
www.devcode.la
Redux puede ser descrito en tres principios fundamentales
www.devcode.la
El estado de toda tu aplicación esta almacenado en un árbol guardado en un único store.
www.devcode.la
https://css-tricks.com/learning-react-redux/
www.devcode.la
console.log(store.getState())
/* Imprime
{
visibilityFilter: 'SHOW_ALL',
todos: [
{
text: 'Considerar usar Redux',
completed: true
},
{
text: 'Mantener todo el estado en un solo árbol',
completed: false
}
]
}
*/
www.devcode.la
La única forma de modificar el estado es emitiendo una acción, un objeto describiendo que ocurrió.
www.devcode.la
store.dispatch({
type: 'COMPLETE_TODO',
index: 1
});
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter: 'SHOW_COMPLETED'
});
www.devcode.la
Para especificar como el árbol de estado es transformado por las acciones, se utilizan reducers puros.
www.devcode.la
www.devcode.la
- Sin Angular
- Sin ngrx
- Solo ts y redux
www.devcode.la
www.devcode.la
mkdir todos-redux
www.devcode.la
{
"name": "todos-redux",
"version": "1.0.0",
"description": "",
"author": "",
"license": "MIT",
"devDependencies": {
"ts-node": "3.3.0",
"typescript": "2.4.2"
},
"dependencies": {
"redux": "3.7.2"
}
}
package.json
www.devcode.la
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noEmitHelpers": true,
"sourceMap": true,
"lib": [
"es2016",
"dom"
]
},
"compileOnSave": false,
"buildOnSave": false
}
tsconfig.json
www.devcode.la
npm install
www.devcode.la
import { createStore } from 'redux';
console.log("Compile!!!")
index.ts
www.devcode.la
./node_modules/.bin/ts-node index.ts
run
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
- Debe retornar el mismo tipo de data en el que es definido el reducer
- Por defecto debe retornar el estado original
- Debería recibir un estado inicial
- Crear un nuevo estado
www.devcode.la
interface Action{
type: string;
payload?: any;
}
www.devcode.la
interface Reducer<T>{
(state: T, action: Action): T;
}
www.devcode.la
www.devcode.la
La única forma de modificar el estado es emitiendo una acción, un objeto describiendo que ocurrió
www.devcode.la
interface Action{
type: string;
payload?: any;
}
www.devcode.la
if(action.type === 'INCREMENT'){
return state + 1;
}
if(action.type === 'DECREMENT'){
return state - 1;
}
www.devcode.la
switch(action.type){
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
www.devcode.la
switch(action.type){
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state + 1;
case 'PLUS':
return state + action.payload;
default:
return state;
}
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
{
todos: [{
text: 'Aprender redux',
completed: true
}, {
text: 'Visitar nicobytes.com',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}
www.devcode.la
class Store<T>{
private state:T;
constructor(
private reducer: Reducer<T>,
initState: T
){
this.state = initState;
}
}
www.devcode.la
getState(): T{
return this.state;
}
www.devcode.la
dispatch(action: Action): void{
this.state = this.reducer(this.state, action);
}
www.devcode.la
let store = new Store<number>(reducer, 0);
www.devcode.la
store.dispatch({type: 'INCREMENT'});
www.devcode.la
console.log(store.getState());
www.devcode.la
www.devcode.la
import {
Action,
Reducer,
createStore,
Store
} from 'redux';
www.devcode.la
interface PlusAction extends Action{
payload: number;
}
www.devcode.la
let reducer: Reducer<number> = (state: number = 0, action: Action)=>{
switch(action.type){
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
case 'PLUS':
return state + (<PlusAction>action).payload;
default:
return state;
}
}
www.devcode.la
let store: Store<number> =
createStore<number>(reducer);
www.devcode.la
console.log(store.getState());
www.devcode.la
store.dispatch(...)
www.devcode.la
store.subscribe(()=>{
console.log(store.getState());
})
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
ng new counter-app-ngrx
www.devcode.la
npm install @ngrx/store --save
www.devcode.la
www.devcode.la
www.devcode.la
let reducer: Reducer<number> = (state: number = 0, action: Action) =>{
if(action === null) return state;
switch(action.type){
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
case 'PLUS':
return state + (<PlusAction>action).payload;
default:
return state;
}
}
www.devcode.la
import { Action } from '@ngrx/store';
export const INCREMENT = '[Counter] increment';
export const DECREMENT = '[Counter] decrement';
export const PLUS = '[Counter] plus';
export const RESET = '[Counter] reset';
export interface PlusAction extends Action{
payload: number;
}
www.devcode.la
www.devcode.la
let reducer: Reducer<number> = (state: number = 0, action: Action) =>{
if(action === null) return state;
switch(action.type){
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
case 'PLUS':
return state + (<PlusAction>action).payload;
default:
return state;
}
}
www.devcode.la
- El estado
- Su reducer
www.devcode.la
www.devcode.la
export interface AppState{
counter: number;
}
www.devcode.la
- El estado
- Su reducer
www.devcode.la
StoreModule.forRoot(rootReducer),
www.devcode.la
www.devcode.la
this.store.select()
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
ng new todo-app-ngrx --sytle scss
www.devcode.la
npm install @ngrx/store --save
npm install @ngrx/store-devtools --save
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
npm install todomvc-common --save
npm install todomvc-app-css --save
www.devcode.la
@import '~todomvc-common/base.css';
@import '~todomvc-app-css/index.css';
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
www.devcode.la
firebase init
ng build --target=production --base-href /
firebase deploy
www.devcode.la
www.devcode.la
https://github.com/DevcodeInc/Curso-de-Angular-4-y-Redux
www.devcode.la
www.devcode.la
https://github.com/nicobytes/todo-app-ngrx/
www.devcode.la
www.devcode.la