Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

RxJS + Redux + React = Amazing

27,392 views

Published on

Manage your redux async/side effects with RxJS using redux-observable middleware. Applies not just to React, also Angular2, Ember, etc.

Published in: Software
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (2019 Update) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { https://soo.gd/irt2 } ......................................................................................................................... Download Full EPUB Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download Full doc Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download PDF EBOOK here { https://soo.gd/irt2 } ......................................................................................................................... Download EPUB Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download doc Ebook here { https://soo.gd/irt2 } ......................................................................................................................... ......................................................................................................................... ................................................................................................................................... eBook is an electronic version of a traditional print book THIS can be read by using a personal computer or by using an eBook reader. (An eBook reader can be a software application for use on a computer such as Microsoft's free Reader application, or a book-sized computer THIS is used solely as a reading device such as Nuvomedia's Rocket eBook.) Users can purchase an eBook on diskette or CD, but the most popular method of getting an eBook is to purchase a downloadable file of the eBook (or other reading material) from a Web site (such as Barnes and Noble) to be read from the user's computer or reading device. Generally, an eBook can be downloaded in five minutes or less ......................................................................................................................... .............. Browse by Genre Available eBooks .............................................................................................................................. Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, ......................................................................................................................... ......................................................................................................................... .....BEST SELLER FOR EBOOK RECOMMEND............................................................. ......................................................................................................................... Blowout: Corrupted Democracy, Rogue State Russia, and the Richest, Most Destructive Industry on Earth,-- The Ride of a Lifetime: Lessons Learned from 15 Years as CEO of the Walt Disney Company,-- Call Sign Chaos: Learning to Lead,-- StrengthsFinder 2.0,-- Stillness Is the Key,-- She Said: Breaking the Sexual Harassment Story THIS Helped Ignite a Movement,-- Atomic Habits: An Easy & Proven Way to Build Good Habits & Break Bad Ones,-- Everything Is Figureoutable,-- What It Takes: Lessons in the Pursuit of Excellence,-- Rich Dad Poor Dad: What the Rich Teach Their Kids About Money THIS the Poor and Middle Class Do Not!,-- The Total Money Makeover: Classic Edition: A Proven Plan for Financial Fitness,-- Shut Up and Listen!: Hard Business Truths THIS Will Help You Succeed, ......................................................................................................................... .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❤❤❤ http://bit.ly/39sFWPG ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ♥♥♥ http://bit.ly/39sFWPG ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD FULL BOOKS, INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... ,DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ,DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ,DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ,DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ,DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ,DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

RxJS + Redux + React = Amazing

  1. 1. RxJS + Redux + React = Amazing Jay Phelps | @_jayphelps Side Effect Management with RxJS
  2. 2. Jay Phelps | @_jayphelps Managing state stuff is hard
  3. 3. Jay Phelps | @_jayphelps Redux makes it simple (not necessarily easy)
  4. 4. Jay Phelps | @_jayphelps Managing async stuff is harder
  5. 5. Jay Phelps | @_jayphelps Some async is complex regardless of the abstraction
  6. 6. Jay Phelps | @_jayphelps RxJS makes it manageable
  7. 7. Jay Phelps Senior Software Engineer | @_jayphelps
  8. 8. What is redux? Jay Phelps | @_jayphelps
  9. 9. Crash Course Jay Phelps | @_jayphelps
  10. 10. What is redux? Jay Phelps | @_jayphelps Provides predicable state management using actions and reducers
  11. 11. What's an "action"? Jay Phelps | @_jayphelps Describes something has (or should) happen, but they don't specify how it should be done
  12. 12. Jay Phelps | @_jayphelps { type: 'CREATE_TODO', payload: 'Build my first Redux app' }
  13. 13. What's an "reducer"? Jay Phelps | @_jayphelps A pure function that takes the previous state and an action and returns the new state
  14. 14. What's an "reducer"? Jay Phelps | @_jayphelps Sometimes it returns the previous state (state, action) => state
  15. 15. What's an "reducer"? Jay Phelps | @_jayphelps Sometimes it computes new state (state, action) => state + action.payload
  16. 16. Jay Phelps | @_jayphelps const counter = (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } };
  17. 17. Jay Phelps | @_jayphelps Reducers handle state transitions, but they must be done synchronously.
  18. 18. Jay Phelps | @_jayphelps const counter = (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } };
  19. 19. Jay Phelps | @_jayphelps What are async stuff do we commonly do?
  20. 20. Async Jay Phelps | @_jayphelps • User interactions (mouse, keyboard, etc) • AJAX • Timers/Animations • Web Sockets • Work Workers, etc
  21. 21. Jay Phelps | @_jayphelps Some can be handled synchronously
  22. 22. Jay Phelps | @_jayphelps <button onClick={() => dispatch({ type: 'INCREMENT' })}> Increment </button>
  23. 23. Jay Phelps | @_jayphelps const counter = (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } };
  24. 24. Jay Phelps | @_jayphelps Sometimes you need more control
  25. 25. Jay Phelps | @_jayphelps • AJAX cancellation/composing • Debounce/throttle/buffer/etc • Drag and Drop • Web Sockets, Work Workers, etc
  26. 26. Jay Phelps | @_jayphelps Use middleware to manage async / side effects
  27. 27. Jay Phelps | @_jayphelps Most of them use callbacks or Promises
  28. 28. Callbacks Jay Phelps | @_jayphelps The most primitive way to handle async in JavaScript
  29. 29. Callbacks Jay Phelps | @_jayphelps fetchSomeData((error, data) => { if (!error) { dispatch({ type: 'HERES_THE_DATA', data }); } });
  30. 30. Callback Hell Jay Phelps | @_jayphelps fetchSomeData(id, (error, data) => { if (!error) { dispatch({ type: 'HERES_THE_FIRST_CALL_DATA', data }); fetchSomeData(data.parentId, (error, data) => { if (!error) { dispatch({ type: 'HERES_SOME_MORE', data }); fetchSomeData(data.parentId, (error, data) => { if (!error) { dispatch({ type: 'OMG_MAKE_IT_STOP', data }); } }); } }); } });
  31. 31. Promises Jay Phelps | @_jayphelps fetchSomeData(id) .then(data => { dispatch({ type: 'HERES_THE_FIRST_CALL_DATA', data }); return fetchSomeData(data.parentId); }) .then(data => { dispatch({ type: 'HERES_SOME_MORE', data }); return fetchSomeData(data.parentId); }) .then(data => { dispatch({ type: 'OKAY_IM_DONE', data }); });
  32. 32. Promises Jay Phelps | @_jayphelps • Guaranteed future • Immutable • Single value • Caching
  33. 33. Promises Jay Phelps | @_jayphelps • Guaranteed future • Immutable • Single value • Caching
  34. 34. Promises Jay Phelps | @_jayphelps • Guaranteed future • Immutable • Single value • Caching
  35. 35. Jay Phelps | @_jayphelps Promises cannot be cancelled
  36. 36. Jay Phelps | @_jayphelps Why would you want to cancel?
  37. 37. Jay Phelps | @_jayphelps • Changing routes/views • Auto-complete • User wants you to
  38. 38. Jay Phelps | @_jayphelps • Changing routes/views • Auto-complete • User wants you to
  39. 39. Jay Phelps | @_jayphelps Daredevil
  40. 40. Jay Phelps | @_jayphelps Daredevil The Get Down Here’s Daredevil!
  41. 41. Jay Phelps | @_jayphelps Daredevil
  42. 42. Jay Phelps | @_jayphelps Daredevil The Get Down
  43. 43. Jay Phelps | @_jayphelps Cancelling is common and often overlooked
  44. 44. Promises Jay Phelps | @_jayphelps • Guaranteed future • Immutable • Single value • Caching
  45. 45. Only AJAX is single value Jay Phelps | @_jayphelps • User interactions (mouse, keyboard, etc • AJAX • Animations • WebSockets, Workers, etc
  46. 46. Jay Phelps | @_jayphelps What do we use?
  47. 47. Jay Phelps | @_jayphelps Observables
  48. 48. Observables Jay Phelps | @_jayphelps • Stream of zero, one, or more values • Over any amount of time • Cancellable
  49. 49. Jay Phelps | @_jayphelps Streams are a set, with a dimension of time
  50. 50. Jay Phelps | @_jayphelps Being standardized for ECMAScript aka JavaScript
  51. 51. RxJS Jay Phelps | @_jayphelps “lodash for async” - Ben Lesh
  52. 52. Crash Course Jay Phelps | @_jayphelps
  53. 53. Creating Observables Jay Phelps | @_jayphelps • of('hello') • from([1, 2, 3, 4]) • interval(1000) • ajax('http://example.com') • webSocket('ws://echo.websocket.com') • fromEvent(button, ‘click') • many more…
  54. 54. Subscribing Jay Phelps | @_jayphelps myObservable.subscribe( value => console.log('next', value) );
  55. 55. Subscribing Jay Phelps | @_jayphelps myObservable.subscribe( value => console.log('next', value), err => console.error('error', err) );
  56. 56. Subscribing Jay Phelps | @_jayphelps myObservable.subscribe( value => console.log('next', value), err => console.error('error', err), () => console.info('complete!') );
  57. 57. Observables can be transformed Jay Phelps | @_jayphelps map, filter, reduce
  58. 58. Observables can be combined Jay Phelps | @_jayphelps concat, merge, zip
  59. 59. Observables represent time Jay Phelps | @_jayphelps debounce, throttle, buffer, combineLatest
  60. 60. Observables are lazy Jay Phelps | @_jayphelps retry, repeat
  61. 61. Jay Phelps | @_jayphelps Observables can represent just about anything
  62. 62. Jay Phelps | @_jayphelps Let’s combine RxJS and Redux!
  63. 63. Jay Phelps | @_jayphelps
  64. 64. Side effect management for redux, using Epics
  65. 65. What is an Epic? Jay Phelps | @_jayphelps A function that takes a stream of all actions dispatched and returns a stream of new actions to dispatch
  66. 66. Jay Phelps | @_jayphelps “actions in, actions out”
  67. 67. // This is pseudo code, not real function pingPong(action, store) { if (action.type === 'PING') { return { type: 'PONG' }; } } Jay Phelps | @_jayphelps Sort of like this
  68. 68. function pingPongEpic(action$, store) { return action$.ofType('PING') .map(action => ({ type: 'PONG' })); } An Epic Jay Phelps | @_jayphelps
  69. 69. const pingPongEpic = (action$, store) => action$.ofType('PING') .map(action => ({ type: 'PONG' })); An Epic Jay Phelps | @_jayphelps
  70. 70. An Epic Jay Phelps | @_jayphelps const pingPongEpic = (action$, store) => action$.ofType('PING') .delay(1000) // <— that's it .map(action => ({ type: 'PONG' }));
  71. 71. Jay Phelps | @_jayphelps const isPinging = (state = false, action) => { switch (action.type) { case 'PING': return true; case 'PONG': return false; default: return state; } };
  72. 72. const pingPongEpic = (action$, store) => action$.ofType('PING') .delay(1000) .map(action => ({ type: 'PONG' })); Jay Phelps | @_jayphelps
  73. 73. Jay Phelps | @_jayphelps Debounced increment / decrement button
  74. 74. Jay Phelps | @_jayphelps const counter = (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } };
  75. 75. Jay Phelps | @_jayphelps const incrementEpic = (action$, store) => action$.ofType('INCREMENT_DEBOUNCED') .debounceTime(1000) .map(() => ({ type: 'INCREMENT' })); const decrementEpic = (action$, store) => action$.ofType('DECREMENT_DEBOUNCED') .debounceTime(1000) .map(() => ({ type: 'DECREMENT' }));
  76. 76. Jay Phelps | @_jayphelps const incrementEpic = (action$, store) => action$.ofType('INCREMENT_DEBOUNCED') .debounceTime(1000) .map(() => ({ type: 'INCREMENT' })); const decrementEpic = (action$, store) => action$.ofType('DECREMENT_DEBOUNCED') .debounceTime(1000) .map(() => ({ type: 'DECREMENT' }));
  77. 77. Jay Phelps | @_jayphelps Those are contrived examples, obviously
  78. 78. Jay Phelps | @_jayphelps Warning: non-trivial examples ahead, don’t struggle to read them entirely
  79. 79. Jay Phelps | @_jayphelps Auto-complete
  80. 80. Jay Phelps | @_jayphelps onKeyUp(e) { const { store } = this.props; const { value } = e.target.value; if (this.queryId) { clearTimeout(this.queryId); } this.queryId = setTimeout(() => { if (this.xhr) { this.xhr.abort(); } const xhr = this.xhr = new XMLHttpRequest(); xhr.open('GET', 'https://api.github.com/search/users?q=' + value); xhr.onload = () => { if (xhr.status === 200) { store.dispatch({ type: 'QUERY_FULFILLED', payload: JSON.parse(xhr.response).items }); } else { store.dispatch({ type: 'QUERY_REJECTED', error: true, payload: { message: xhr.response, status: xhr.status } }); } }; xhr.send(); }, 500); } Plain JS
  81. 81. Jay Phelps | @_jayphelps Epic const autoCompleteEpic = (action$, store) => action$.ofType('QUERY') .debounceTime(500) .switchMap(action => ajax('https://api.github.com/search/users?q=' + value) .map(payload => ({ type: 'QUERY_FULFILLED', payload })) );
  82. 82. Jay Phelps | @_jayphelps Epic const autoCompleteEpic = (action$, store) => action$.ofType('QUERY') .debounceTime(500) .switchMap(action => ajax('https://api.github.com/search/users?q=' + value) .map(payload => ({ type: 'QUERY_FULFILLED', payload })) .catch(payload => [{ type: 'QUERY_REJECTED', error: true, payload }]) );
  83. 83. Jay Phelps | @_jayphelps Epic const autoCompleteEpic = (action$, store) => action$.ofType('QUERY') .debounceTime(500) .switchMap(action => ajax('https://api.github.com/search/users?q=' + value) .map(payload => ({ type: 'QUERY_FULFILLED', payload })) .takeUntil(action$.ofType('CANCEL_QUERY')) .catch(payload => [{ type: 'QUERY_REJECTED', error: true, payload }]) );
  84. 84. Jay Phelps | @_jayphelps OK, show me really non-trivial examples
  85. 85. Jay Phelps | @_jayphelps Bidirectional, multiplexed Web Sockets
  86. 86. Jay Phelps | @_jayphelps class Example { @autobind checkChange(e) { const { value: key, checked } = e.target; this.subs = this.subs || []; if (checked) { const handler = e => { const data = JSON.parse(e.data); if (data.key === key) { this.updateValue(key, data.value); } }; this.subs.push({ key, handler }) const socket = this.getSocket(() => { this.setState({ socketOpen: true }); this.subs.forEach(({ key }) => socket.send(JSON.stringify({ type: 'sub', key}))); }); socket.addEventListener('message', handler); } else { const index = this.subs.findIndex(x => x.key === key); if (index !== -1) { this.subs.splice(index, 1); } const { socket } = this; if (socket && socket.readyState === 1) { socket.send(JSON.stringify({ type: 'unsub', key })); this.setInactive(key)l if (this.subs.length === 0) { socket.close(); } } } } componentWillUnMount() { if (this.socket && this.socket.readyState === 1) { this.socket.close(); } } Plain JS getSocket(callback) { const { socket } = this; if (socket && socket.readyState === 1) { setTimeot(callback); } else { if (this.reconnectId) { clearTimeout(this.reconnectId); } socket = this.socket = new WebSocket(‘ws://localhost:3000'); socket.onopen = () => { callback(); }; socket.onerror = () => { this.reconnectId = setTimeout(() => this.getSocket(callback), 1000); this.setState({ socketOpen: false }); }; socket.onclose = (e) => { if (!e.wasClean) { this.reconnectId = setTimeout(() => this.getSocket(callback), 1000); } this.setState({ socketOpen: false }); }; } return socket; } }
  87. 87. Jay Phelps | @_jayphelps Too much code
  88. 88. Jay Phelps | @_jayphelps As an Epic const socket = WebSocketSubject.create('ws://stock/endpoint'); const stockTickerEpic = (action$, store) => action$.ofType('START_TICKER_STREAM') .mergeMap(action => socket.multiplex( () => ({ sub: action.ticker }), () => ({ unsub: action.ticker }), msg => msg.ticker === action.ticker ) .retryWhen( err => window.navigator.onLine ? Observable.timer(1000) : Observable.fromEvent(window, 'online') ) .takeUntil( action$.ofType('CLOSE_TICKER_STREAM') .filter(closeAction => closeAction.ticker === action.ticker) ) .map(tick => ({ type: 'TICKER_TICK', tick })) );
  89. 89. redux-observable Jay Phelps | @_jayphelps • Makes it easier to compose and control complex async tasks, over any amount of time • You don't need to manage your own Rx subscriptions • You can use redux tooling
  90. 90. But… Jay Phelps | @_jayphelps
  91. 91. Jay Phelps | @_jayphelps You should probably know redux and RxJS in advance
  92. 92. Jay Phelps | @_jayphelps RxJS has a bit of a learning curve
  93. 93. Jay Phelps | @_jayphelps “Reactive Programming”
  94. 94. Co-author Jay Phelps | @_jayphelps Ben Lesh Senior UI Engineer | @benlesh
  95. 95. Jay Phelps | @_jayphelps https://redux-observable.js.org
  96. 96. Thanks! @_jayphelps

×