Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Complex State Handling in Modern Web Apps | Filip Danić @ Voxxed Days Belgrade 2016

Filip Danić
September 30, 2016

Complex State Handling in Modern Web Apps | Filip Danić @ Voxxed Days Belgrade 2016

Slides from my talk on Redux and Voxxed Days Belgrade 2016 (#vdb16).

Follow me on twitter @DanicFilip or visit my site danicfilip.com

Filip Danić

September 30, 2016
Tweet

More Decks by Filip Danić

Other Decks in Programming

Transcript

  1. Reducers. function productsReducer(state = initialState, action) { switch (action.type) {

    case GET_PRODUCTS: return Object.assign({}, state, { products: action.payload.products, timestamp: action.payload.timestamp, }); default: return state; } }
  2. With Immutable.js function productsReducer(state = initialState, action) { switch (action.type)

    { case GET_PRODUCTS: return state .set(‘products’, action.payload.products) .set(‘timestamp’, action.payload.timestamp); default: return state; } }
  3. Compassable. const middleware = [sagaMiddleware, loggerMiddleware]; const store = createStore(

    createReducer(), initialState, compose(…applyMiddleware(...middleware)), );
  4. Write tests! describe('reducers', () => { describe('products', () => {

    it('should handle GET_PRODUCTS action', () => { const action = { type: GET_PRODUCTS, products: [{id: 1, title: 'Product 1'}, {id: 2, title: ’Product 2'}], }; expect(products({}, action)).toEqual({byId: {1: {id: 1, title: 'Product 1'}, 2: {id: 2, title: 'Product 2’}}}); }); /…
  5. function* countToN(n) { for (let i = 1; i <=

    n; i++) {
 yield i; } } const gen = countToN(5); Generators
  6. gen.next(); // {value: 1, done: false} gen.next(); // {value: 2,

    done: false} gen.next(); // {value: 3, done: false} gen.next(); // {value: 4, done: false} gen.next(); // {value: 5, done: false} gen.next(); // {done: true}
  7. function* getProducts() { while (true) { const watcher = yield

    race({ list: take(GET_ALL_PRODUCTS), stop: take(LOCATION_CHANGE), }); if (watcher.stop) break; const { data } = list.payload; const list = yield call(ProductsService.getAll, data); if (list.err) { yield put(getProductsError(list.err)); } else { yield put(getProductsSuccess(list.response)); } } } Saga
  8. function* getAll() { const task1 = yield fork(ProductService.getAll, ‘products’) const

    task2 = yield fork(UserService.getAll, ‘users’) } Forks!
  9. function notificationsChannel() { return eventChannel(emitter => { const source =

    new EventSource(URL); source.addEventListener('message', e => { emitter(JSON.parse(e.data)); }); return () => source.close(); }); } Event Channel
  10. function* notificationsSaga() { const channel = yield call(notificationsChannel); while (true)

    { const notification yield take(channel); yield put(loadNotification(notification)); }); } Event Channel + Saga