How & why use Redux with Angular 1
A.K.A. the beauty and the beast
1) redux recap
2) redux with angular
3) feedback on real app
1) redux recap
state
An action is dispatched
And goes though reducers
new state
component
Components are connected to the state
(previousState, action) => newState
Three principles
- Single source of truth
- State is read-only
- Changes are made with pure functions
2) redux with angular
package.json
"immutable": "^3.8.1",
"ng-redux": "^3.4.0-beta.1",
"redux": "^3.6.0",
"redux-thunk": "^2.1.0",
"reselect": "^2.5.3",
this[CREATE_START] = state => state;
this[CREATE_SUCCESS] = (state, {todo}) => {
return state.set(todo.id, immutable.fromJS(todo));
};
this[CREATE_ERROR] = state => state;
this.reducer = (state = initialState, {type, payload}) => {
return typeof this[type] === 'function' ? this[type](state, payload) : state;
};
reducer example
this.reducer = function (state = initialState, action) {
switch (action.type) {
case 'CREATE_START':
return state;
case 'CREATE_SUCCESS':
return state.set(action.todo.id, immutable.fromJS(action.todo));
case 'CREATE_START':
return state;
default:
return state;
}
};
another kind of reducer (with switch)
this.create = todoName => dispatch => {
dispatch(this.createStart());
// Yay! Can invoke sync or async actions with `dispatch`
// Thanks to redux-thunk
$http({
url: '/api/todo',
method: 'POST',
data: {
name: todoName
}
})
.then(response => {
dispatch(this.createSuccess(response.data));
})
.catch(error => {
dispatch(this.createError(error));
})
};
actions example
export default function TodolistController($ngRedux, todoActions) {
$ngRedux.dispatch(todoActions.fetch());
this.$onDestroy = $ngRedux.connect(state => {
const todos = state.todos.toArray();
return {
todos
};
})(this);
}
controller (connect + dispatch)
import { createSelector } from 'reselect'
const shopItemsSelector = state => state.shop.items
const taxPercentSelector = state => state.shop.taxPercent
const subtotalSelector = createSelector(
shopItemsSelector,
items => items.reduce((acc, item) => acc + item.value, 0)
)
const taxSelector = createSelector(
subtotalSelector,
taxPercentSelector,
(subtotal, taxPercent) => subtotal * (taxPercent / 100)
)
let exampleState = {
shop: {
taxPercent: 8,
items: [
{ name: 'apple', value: 1.20 },
{ name: 'orange', value: 0.95 },
]
}
}
console.log(subtotalSelector(exampleState)) // 2.15
console.log(taxSelector(exampleState)) // 0.172
reselect
Demo time
A.K.A. another todo app
3) feedback on real app
Pros
- Easy to implement feature that would be complicated otherwise (loading states, undo/redo, deactivating some API calls ...)
- Awesome debugger extension
- Makes it easier to structure a big application
Cons
- Chrome extension is laggy
- Immutable JS ?! (perf issues, can't be used in ng-repeat, unclear if using immutable or object)
- Need to convince people
When to use redux
- One view depends on multiple API calls
- Multiple source of data (http, websocket) that needs to be unified
In general, use Redux when you have reasonable amounts of data changing over time, you need a single source of truth, and you find that approaches like keeping everything in a top-level React component's state are no longer sufficient.
When not to use redux
- The app is straightforward and it would be overkill
- In half of the application
- For animations
Thank you !
Questions ?
https://github.com/william26/ng-redux-tuto
http://stackoverflow.com/questions/39227832/advantages-of-using-immutable-js-over-object-assign-or-spread-operators
https://github.com/reactjs/reselect
http://redux.js.org/
http://www.meetic.fr/d/onlines
How & why use Redux with Angular 1
By Alexandre BARBIER
How & why use Redux with Angular 1
- 493