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

Complex State Handling in Modern Web Apps | Fil...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Filip Danić 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

Avatar for Filip Danić

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