SlideShare a Scribd company logo
1 of 98
Download to read offline
RxJS + Redux + React = Amazing
Jay Phelps | @_jayphelps
Side Effect Management with RxJS
Jay Phelps | @_jayphelps
Managing state stuff is hard
Jay Phelps | @_jayphelps
Redux makes it simple
(not necessarily easy)
Jay Phelps | @_jayphelps
Managing async stuff is harder
Jay Phelps | @_jayphelps
Some async is complex regardless
of the abstraction
Jay Phelps | @_jayphelps
RxJS makes it manageable
Jay Phelps
Senior Software Engineer |
@_jayphelps
What is redux?
Jay Phelps | @_jayphelps
Crash Course
Jay Phelps | @_jayphelps
What is redux?
Jay Phelps | @_jayphelps
Provides predicable state management using
actions and reducers
What's an "action"?
Jay Phelps | @_jayphelps
Describes something has (or should) happen, but
they don't specify how it should be done
Jay Phelps | @_jayphelps
{	
		type:	'CREATE_TODO',	
		payload:	'Build	my	first	Redux	app'	
}
What's an "reducer"?
Jay Phelps | @_jayphelps
A pure function that takes the previous state
and an action and returns the new state
What's an "reducer"?
Jay Phelps | @_jayphelps
Sometimes it returns the previous state
(state,	action)	=>	state
What's an "reducer"?
Jay Phelps | @_jayphelps
Sometimes it computes new state
(state,	action)	=>	state	+	action.payload
Jay Phelps | @_jayphelps
const	counter	=	(state	=	0,	action)	=>	{	
		switch	(action.type)	{	
				case	'INCREMENT':	
						return	state	+	1;	
				case	'DECREMENT':	
						return	state	-	1;	
						
				default:	
						return	state;	
		}	
};
Jay Phelps | @_jayphelps
Reducers handle state transitions, but they
must be done synchronously.
Jay Phelps | @_jayphelps
const	counter	=	(state	=	0,	action)	=>	{	
		switch	(action.type)	{	
				case	'INCREMENT':	
						return	state	+	1;	
				case	'DECREMENT':	
						return	state	-	1;	
						
				default:	
						return	state;	
		}	
};
Jay Phelps | @_jayphelps
What are async stuff do we commonly do?
Async
Jay Phelps | @_jayphelps
• User interactions (mouse, keyboard, etc)
• AJAX
• Timers/Animations
• Web Sockets
• Work Workers, etc
Jay Phelps | @_jayphelps
Some can be handled synchronously
Jay Phelps | @_jayphelps
<button	onClick={()	=>	dispatch({	type:	'INCREMENT'	})}>	
		Increment	
</button>
Jay Phelps | @_jayphelps
const	counter	=	(state	=	0,	action)	=>	{	
		switch	(action.type)	{	
				case	'INCREMENT':	
						return	state	+	1;	
				case	'DECREMENT':	
						return	state	-	1;	
						
				default:	
						return	state;	
		}	
};
Jay Phelps | @_jayphelps
Sometimes you need more control
Jay Phelps | @_jayphelps
• AJAX cancellation/composing
• Debounce/throttle/buffer/etc
• Drag and Drop
• Web Sockets, Work Workers, etc
Jay Phelps | @_jayphelps
Use middleware to manage async / side effects
Jay Phelps | @_jayphelps
Most of them use callbacks or Promises
Callbacks
Jay Phelps | @_jayphelps
The most primitive way to handle async in JavaScript
Callbacks
Jay Phelps | @_jayphelps
fetchSomeData((error,	data)	=>	{	
		if	(!error)	{	
				dispatch({	type:	'HERES_THE_DATA',	data	});	
		}	
});
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	});	
										}	
								});	
						}	
				});	
		}	
});
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	});	
		});
Promises
Jay Phelps | @_jayphelps
• Guaranteed future
• Immutable
• Single value
• Caching
Promises
Jay Phelps | @_jayphelps
• Guaranteed future
• Immutable
• Single value
• Caching
Promises
Jay Phelps | @_jayphelps
• Guaranteed future
• Immutable
• Single value
• Caching
Jay Phelps | @_jayphelps
Promises cannot be cancelled
Jay Phelps | @_jayphelps
Why would you want to cancel?
Jay Phelps | @_jayphelps
• Changing routes/views
• Auto-complete
• User wants you to
Jay Phelps | @_jayphelps
• Changing routes/views
• Auto-complete
• User wants you to
Jay Phelps | @_jayphelps
Daredevil
Jay Phelps | @_jayphelps
Daredevil	
The	Get	Down	
Here’s	Daredevil!
Jay Phelps | @_jayphelps
Daredevil
Jay Phelps | @_jayphelps
Daredevil	
The	Get	Down
Jay Phelps | @_jayphelps
Cancelling is common and often overlooked
Promises
Jay Phelps | @_jayphelps
• Guaranteed future
• Immutable
• Single value
• Caching
Only AJAX is single value
Jay Phelps | @_jayphelps
• User interactions (mouse, keyboard, etc
• AJAX
• Animations
• WebSockets, Workers, etc
Jay Phelps | @_jayphelps
What do we use?
Jay Phelps | @_jayphelps
Observables
Observables
Jay Phelps | @_jayphelps
• Stream of zero, one, or more values
• Over any amount of time
• Cancellable
Jay Phelps | @_jayphelps
Streams are a set, with a dimension of time
Jay Phelps | @_jayphelps
Being standardized for ECMAScript aka JavaScript
RxJS
Jay Phelps | @_jayphelps
“lodash for async” - Ben Lesh
Crash Course
Jay Phelps | @_jayphelps
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…
Subscribing
Jay Phelps | @_jayphelps
myObservable.subscribe(	
		value	=>	console.log('next',	value)	
);
Subscribing
Jay Phelps | @_jayphelps
myObservable.subscribe(	
		value	=>	console.log('next',	value),	
		err	=>	console.error('error',	err)	
);
Subscribing
Jay Phelps | @_jayphelps
myObservable.subscribe(	
		value	=>	console.log('next',	value),	
		err	=>	console.error('error',	err),	
		()	=>	console.info('complete!')	
);
Observables can be transformed
Jay Phelps | @_jayphelps
map, filter, reduce
Observables can be combined
Jay Phelps | @_jayphelps
concat, merge, zip
Observables represent time
Jay Phelps | @_jayphelps
debounce, throttle, buffer, combineLatest
Observables are lazy
Jay Phelps | @_jayphelps
retry, repeat
Jay Phelps | @_jayphelps
Observables can represent just about anything
Jay Phelps | @_jayphelps
Let’s combine RxJS and Redux!
Jay Phelps | @_jayphelps
Side effect management for redux, using Epics
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
Jay Phelps | @_jayphelps
“actions in, actions out”
//	This	is	pseudo	code,	not	real	
function	pingPong(action,	store)	{	
		if	(action.type	===	'PING')	{	
				return	{	type:	'PONG'	};	
		}	
}
Jay Phelps | @_jayphelps
Sort of like this
function	pingPongEpic(action$,	store)	{	
		return	action$.ofType('PING')	
				.map(action	=>	({	type:	'PONG'	}));	
}
An Epic
Jay Phelps | @_jayphelps
const	pingPongEpic	=	(action$,	store)	=>	
		action$.ofType('PING')	
				.map(action	=>	({	type:	'PONG'	}));
An Epic
Jay Phelps | @_jayphelps
An Epic
Jay Phelps | @_jayphelps
const	pingPongEpic	=	(action$,	store)	=>	
		action$.ofType('PING')	
				.delay(1000)	//	<—	that's	it	
				.map(action	=>	({	type:	'PONG'	}));
Jay Phelps | @_jayphelps
const	isPinging	=	(state	=	false,	action)	=>	{	
		switch	(action.type)	{	
				case	'PING':	
						return	true;	
				case	'PONG':	
						return	false;	
				default:	
						return	state;	
		}	
};
const	pingPongEpic	=	(action$,	store)	=>	
		action$.ofType('PING')	
				.delay(1000)	
				.map(action	=>	({	type:	'PONG'	}));
Jay Phelps | @_jayphelps
Jay Phelps | @_jayphelps
Debounced increment / decrement button
Jay Phelps | @_jayphelps
const	counter	=	(state	=	0,	action)	=>	{	
		switch	(action.type)	{	
				case	'INCREMENT':	
						return	state	+	1;	
				case	'DECREMENT':	
						return	state	-	1;	
						
				default:	
						return	state;	
		}	
};
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'	}));
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'	}));
Jay Phelps | @_jayphelps
Those are contrived examples, obviously
Jay Phelps | @_jayphelps
Warning: non-trivial examples ahead,
don’t struggle to read them entirely
Jay Phelps | @_jayphelps
Auto-complete
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
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	
								}))	
				);
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	
								}])	
				);
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	
								}])	
				);
Jay Phelps | @_jayphelps
OK, show me really non-trivial examples
Jay Phelps | @_jayphelps
Bidirectional, multiplexed Web Sockets
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;	
		}	
}
Jay Phelps | @_jayphelps
Too much code
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	}))	
				);
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
But…
Jay Phelps | @_jayphelps
Jay Phelps | @_jayphelps
You should probably know redux and RxJS in advance
Jay Phelps | @_jayphelps
RxJS has a bit of a learning curve
Jay Phelps | @_jayphelps
“Reactive Programming”
Co-author
Jay Phelps | @_jayphelps
Ben Lesh
Senior UI Engineer |
@benlesh
Jay Phelps | @_jayphelps
https://redux-observable.js.org
Thanks!
@_jayphelps

More Related Content

What's hot

Redux Toolkit - Quick Intro - 2022
Redux Toolkit - Quick Intro - 2022Redux Toolkit - Quick Intro - 2022
Redux Toolkit - Quick Intro - 2022Fabio Biondi
 
Getting started with Redux js
Getting started with Redux jsGetting started with Redux js
Getting started with Redux jsCitrix
 
React.js and Redux overview
React.js and Redux overviewReact.js and Redux overview
React.js and Redux overviewAlex Bachuk
 
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...Philip Schwarz
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux IntroductionNikolaus Graf
 
Basics of React Hooks.pptx.pdf
Basics of React Hooks.pptx.pdfBasics of React Hooks.pptx.pdf
Basics of React Hooks.pptx.pdfKnoldus Inc.
 
React Class Components vs Functional Components: Which is Better?
React Class Components vs Functional Components: Which is Better?React Class Components vs Functional Components: Which is Better?
React Class Components vs Functional Components: Which is Better?Fibonalabs
 
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with ThymeleafSpring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with ThymeleafThymeleaf
 
An introduction to React.js
An introduction to React.jsAn introduction to React.js
An introduction to React.jsEmanuele DelBono
 
React js programming concept
React js programming conceptReact js programming concept
React js programming conceptTariqul islam
 
Node.js and the MySQL Document Store
Node.js and the MySQL Document StoreNode.js and the MySQL Document Store
Node.js and the MySQL Document StoreRui Quelhas
 
An Introduction to ReactJS
An Introduction to ReactJSAn Introduction to ReactJS
An Introduction to ReactJSAll Things Open
 
Introduction to react
Introduction to reactIntroduction to react
Introduction to reactkiranabburi
 
Introduction to JSX
Introduction to JSXIntroduction to JSX
Introduction to JSXMicah Wood
 
Java EE Introduction
Java EE IntroductionJava EE Introduction
Java EE Introductionejlp12
 

What's hot (20)

React native
React nativeReact native
React native
 
Redux Toolkit - Quick Intro - 2022
Redux Toolkit - Quick Intro - 2022Redux Toolkit - Quick Intro - 2022
Redux Toolkit - Quick Intro - 2022
 
Getting started with Redux js
Getting started with Redux jsGetting started with Redux js
Getting started with Redux js
 
React.js and Redux overview
React.js and Redux overviewReact.js and Redux overview
React.js and Redux overview
 
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
 
Basics of React Hooks.pptx.pdf
Basics of React Hooks.pptx.pdfBasics of React Hooks.pptx.pdf
Basics of React Hooks.pptx.pdf
 
React Class Components vs Functional Components: Which is Better?
React Class Components vs Functional Components: Which is Better?React Class Components vs Functional Components: Which is Better?
React Class Components vs Functional Components: Which is Better?
 
ReactJS
ReactJSReactJS
ReactJS
 
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with ThymeleafSpring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
 
Reactjs
Reactjs Reactjs
Reactjs
 
An introduction to React.js
An introduction to React.jsAn introduction to React.js
An introduction to React.js
 
React js programming concept
React js programming conceptReact js programming concept
React js programming concept
 
react redux.pdf
react redux.pdfreact redux.pdf
react redux.pdf
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Node.js and the MySQL Document Store
Node.js and the MySQL Document StoreNode.js and the MySQL Document Store
Node.js and the MySQL Document Store
 
An Introduction to ReactJS
An Introduction to ReactJSAn Introduction to ReactJS
An Introduction to ReactJS
 
Introduction to react
Introduction to reactIntroduction to react
Introduction to react
 
Introduction to JSX
Introduction to JSXIntroduction to JSX
Introduction to JSX
 
Java EE Introduction
Java EE IntroductionJava EE Introduction
Java EE Introduction
 

Similar to RxJS + Redux + React = Amazing

Real-time Insights, powered by Reactive Programming
Real-time Insights, powered by Reactive ProgrammingReal-time Insights, powered by Reactive Programming
Real-time Insights, powered by Reactive ProgrammingJay Phelps
 
React, Powered by WebAssembly
React, Powered by WebAssemblyReact, Powered by WebAssembly
React, Powered by WebAssemblyJay Phelps
 
The WebAssembly Revolution Has Begun
The WebAssembly Revolution Has BegunThe WebAssembly Revolution Has Begun
The WebAssembly Revolution Has BegunJay Phelps
 
Backpressure? Resistance is not futile. (Uphill Conf 2019)
Backpressure? Resistance is not futile. (Uphill Conf 2019)Backpressure? Resistance is not futile. (Uphill Conf 2019)
Backpressure? Resistance is not futile. (Uphill Conf 2019)Jay Phelps
 
WebAssembly Demystified
WebAssembly DemystifiedWebAssembly Demystified
WebAssembly DemystifiedJay Phelps
 
Asynchronous Interfaces
Asynchronous InterfacesAsynchronous Interfaces
Asynchronous Interfacesmaccman
 
WebAssembly. Neither Web Nor Assembly, All Revolutionary
WebAssembly. Neither Web Nor Assembly, All RevolutionaryWebAssembly. Neither Web Nor Assembly, All Revolutionary
WebAssembly. Neither Web Nor Assembly, All RevolutionaryC4Media
 
Intro to php
Intro to phpIntro to php
Intro to phpSp Singh
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everythingnoelrap
 
Entry-level PHP for WordPress
Entry-level PHP for WordPressEntry-level PHP for WordPress
Entry-level PHP for WordPresssprclldr
 
Ditching JQuery
Ditching JQueryDitching JQuery
Ditching JQueryhowlowck
 
Effectively Testing Services - Burlington Ruby Conf
Effectively Testing Services - Burlington Ruby ConfEffectively Testing Services - Burlington Ruby Conf
Effectively Testing Services - Burlington Ruby Confneal_kemp
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptGuy Royse
 
P H P Part I I, By Kian
P H P  Part  I I,  By  KianP H P  Part  I I,  By  Kian
P H P Part I I, By Kianphelios
 
Test driven APIs with Laravel
Test driven APIs with LaravelTest driven APIs with Laravel
Test driven APIs with LaravelMichael Peacock
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
DOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQueryDOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQueryRemy Sharp
 
You don’t know JS about SharePoint - Mastering javascript performance (Hugh W...
You don’t know JS about SharePoint - Mastering javascript performance (Hugh W...You don’t know JS about SharePoint - Mastering javascript performance (Hugh W...
You don’t know JS about SharePoint - Mastering javascript performance (Hugh W...Rencore
 

Similar to RxJS + Redux + React = Amazing (20)

Real-time Insights, powered by Reactive Programming
Real-time Insights, powered by Reactive ProgrammingReal-time Insights, powered by Reactive Programming
Real-time Insights, powered by Reactive Programming
 
React, Powered by WebAssembly
React, Powered by WebAssemblyReact, Powered by WebAssembly
React, Powered by WebAssembly
 
The WebAssembly Revolution Has Begun
The WebAssembly Revolution Has BegunThe WebAssembly Revolution Has Begun
The WebAssembly Revolution Has Begun
 
Backpressure? Resistance is not futile. (Uphill Conf 2019)
Backpressure? Resistance is not futile. (Uphill Conf 2019)Backpressure? Resistance is not futile. (Uphill Conf 2019)
Backpressure? Resistance is not futile. (Uphill Conf 2019)
 
WebAssembly Demystified
WebAssembly DemystifiedWebAssembly Demystified
WebAssembly Demystified
 
Asynchronous Interfaces
Asynchronous InterfacesAsynchronous Interfaces
Asynchronous Interfaces
 
WebAssembly. Neither Web Nor Assembly, All Revolutionary
WebAssembly. Neither Web Nor Assembly, All RevolutionaryWebAssembly. Neither Web Nor Assembly, All Revolutionary
WebAssembly. Neither Web Nor Assembly, All Revolutionary
 
Intro to php
Intro to phpIntro to php
Intro to php
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Entry-level PHP for WordPress
Entry-level PHP for WordPressEntry-level PHP for WordPress
Entry-level PHP for WordPress
 
Ditching JQuery
Ditching JQueryDitching JQuery
Ditching JQuery
 
Jsf Ajax
Jsf AjaxJsf Ajax
Jsf Ajax
 
Effectively Testing Services - Burlington Ruby Conf
Effectively Testing Services - Burlington Ruby ConfEffectively Testing Services - Burlington Ruby Conf
Effectively Testing Services - Burlington Ruby Conf
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
 
P H P Part I I, By Kian
P H P  Part  I I,  By  KianP H P  Part  I I,  By  Kian
P H P Part I I, By Kian
 
Test driven APIs with Laravel
Test driven APIs with LaravelTest driven APIs with Laravel
Test driven APIs with Laravel
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
DOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQueryDOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQuery
 
JSF 2.0 Preview
JSF 2.0 PreviewJSF 2.0 Preview
JSF 2.0 Preview
 
You don’t know JS about SharePoint - Mastering javascript performance (Hugh W...
You don’t know JS about SharePoint - Mastering javascript performance (Hugh W...You don’t know JS about SharePoint - Mastering javascript performance (Hugh W...
You don’t know JS about SharePoint - Mastering javascript performance (Hugh W...
 

More from Jay Phelps

Backpressure? Resistance is not futile. RxJS Live 2019
Backpressure? Resistance is not futile. RxJS Live 2019Backpressure? Resistance is not futile. RxJS Live 2019
Backpressure? Resistance is not futile. RxJS Live 2019Jay Phelps
 
Why I Love JSX!
Why I Love JSX!Why I Love JSX!
Why I Love JSX!Jay Phelps
 
ES2015 and Beyond
ES2015 and BeyondES2015 and Beyond
ES2015 and BeyondJay Phelps
 
Intro to Ember CLI
Intro to Ember CLIIntro to Ember CLI
Intro to Ember CLIJay Phelps
 
Ember Overview in 5 Minutes
Ember Overview in 5 MinutesEmber Overview in 5 Minutes
Ember Overview in 5 MinutesJay Phelps
 
Profit From Your Media Library Using Multi-Platform Distribution
Profit From Your Media Library Using Multi-Platform DistributionProfit From Your Media Library Using Multi-Platform Distribution
Profit From Your Media Library Using Multi-Platform DistributionJay Phelps
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.jsJay Phelps
 

More from Jay Phelps (7)

Backpressure? Resistance is not futile. RxJS Live 2019
Backpressure? Resistance is not futile. RxJS Live 2019Backpressure? Resistance is not futile. RxJS Live 2019
Backpressure? Resistance is not futile. RxJS Live 2019
 
Why I Love JSX!
Why I Love JSX!Why I Love JSX!
Why I Love JSX!
 
ES2015 and Beyond
ES2015 and BeyondES2015 and Beyond
ES2015 and Beyond
 
Intro to Ember CLI
Intro to Ember CLIIntro to Ember CLI
Intro to Ember CLI
 
Ember Overview in 5 Minutes
Ember Overview in 5 MinutesEmber Overview in 5 Minutes
Ember Overview in 5 Minutes
 
Profit From Your Media Library Using Multi-Platform Distribution
Profit From Your Media Library Using Multi-Platform DistributionProfit From Your Media Library Using Multi-Platform Distribution
Profit From Your Media Library Using Multi-Platform Distribution
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.js
 

Recently uploaded

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...software pro Development
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 

Recently uploaded (20)

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 

RxJS + Redux + React = Amazing

  • 1. RxJS + Redux + React = Amazing Jay Phelps | @_jayphelps Side Effect Management with RxJS
  • 2. Jay Phelps | @_jayphelps Managing state stuff is hard
  • 3. Jay Phelps | @_jayphelps Redux makes it simple (not necessarily easy)
  • 4. Jay Phelps | @_jayphelps Managing async stuff is harder
  • 5. Jay Phelps | @_jayphelps Some async is complex regardless of the abstraction
  • 6. Jay Phelps | @_jayphelps RxJS makes it manageable
  • 7. Jay Phelps Senior Software Engineer | @_jayphelps
  • 8. What is redux? Jay Phelps | @_jayphelps
  • 9. Crash Course Jay Phelps | @_jayphelps
  • 10. What is redux? Jay Phelps | @_jayphelps Provides predicable state management using actions and reducers
  • 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. Jay Phelps | @_jayphelps { type: 'CREATE_TODO', payload: 'Build my first Redux app' }
  • 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. What's an "reducer"? Jay Phelps | @_jayphelps Sometimes it returns the previous state (state, action) => state
  • 15. What's an "reducer"? Jay Phelps | @_jayphelps Sometimes it computes new state (state, action) => state + action.payload
  • 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. Jay Phelps | @_jayphelps Reducers handle state transitions, but they must be done synchronously.
  • 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. Jay Phelps | @_jayphelps What are async stuff do we commonly do?
  • 20. Async Jay Phelps | @_jayphelps • User interactions (mouse, keyboard, etc) • AJAX • Timers/Animations • Web Sockets • Work Workers, etc
  • 21. Jay Phelps | @_jayphelps Some can be handled synchronously
  • 22. Jay Phelps | @_jayphelps <button onClick={() => dispatch({ type: 'INCREMENT' })}> Increment </button>
  • 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. Jay Phelps | @_jayphelps Sometimes you need more control
  • 25. Jay Phelps | @_jayphelps • AJAX cancellation/composing • Debounce/throttle/buffer/etc • Drag and Drop • Web Sockets, Work Workers, etc
  • 26. Jay Phelps | @_jayphelps Use middleware to manage async / side effects
  • 27. Jay Phelps | @_jayphelps Most of them use callbacks or Promises
  • 28. Callbacks Jay Phelps | @_jayphelps The most primitive way to handle async in JavaScript
  • 29. Callbacks Jay Phelps | @_jayphelps fetchSomeData((error, data) => { if (!error) { dispatch({ type: 'HERES_THE_DATA', data }); } });
  • 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. 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. Promises Jay Phelps | @_jayphelps • Guaranteed future • Immutable • Single value • Caching
  • 33. Promises Jay Phelps | @_jayphelps • Guaranteed future • Immutable • Single value • Caching
  • 34. Promises Jay Phelps | @_jayphelps • Guaranteed future • Immutable • Single value • Caching
  • 35. Jay Phelps | @_jayphelps Promises cannot be cancelled
  • 36. Jay Phelps | @_jayphelps Why would you want to cancel?
  • 37. Jay Phelps | @_jayphelps • Changing routes/views • Auto-complete • User wants you to
  • 38. Jay Phelps | @_jayphelps • Changing routes/views • Auto-complete • User wants you to
  • 39. Jay Phelps | @_jayphelps Daredevil
  • 40. Jay Phelps | @_jayphelps Daredevil The Get Down Here’s Daredevil!
  • 41. Jay Phelps | @_jayphelps Daredevil
  • 42. Jay Phelps | @_jayphelps Daredevil The Get Down
  • 43. Jay Phelps | @_jayphelps Cancelling is common and often overlooked
  • 44. Promises Jay Phelps | @_jayphelps • Guaranteed future • Immutable • Single value • Caching
  • 45. Only AJAX is single value Jay Phelps | @_jayphelps • User interactions (mouse, keyboard, etc • AJAX • Animations • WebSockets, Workers, etc
  • 46. Jay Phelps | @_jayphelps What do we use?
  • 47. Jay Phelps | @_jayphelps Observables
  • 48. Observables Jay Phelps | @_jayphelps • Stream of zero, one, or more values • Over any amount of time • Cancellable
  • 49. Jay Phelps | @_jayphelps Streams are a set, with a dimension of time
  • 50. Jay Phelps | @_jayphelps Being standardized for ECMAScript aka JavaScript
  • 51. RxJS Jay Phelps | @_jayphelps “lodash for async” - Ben Lesh
  • 52. Crash Course Jay Phelps | @_jayphelps
  • 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. Subscribing Jay Phelps | @_jayphelps myObservable.subscribe( value => console.log('next', value) );
  • 55. Subscribing Jay Phelps | @_jayphelps myObservable.subscribe( value => console.log('next', value), err => console.error('error', err) );
  • 56. Subscribing Jay Phelps | @_jayphelps myObservable.subscribe( value => console.log('next', value), err => console.error('error', err), () => console.info('complete!') );
  • 57. Observables can be transformed Jay Phelps | @_jayphelps map, filter, reduce
  • 58. Observables can be combined Jay Phelps | @_jayphelps concat, merge, zip
  • 59. Observables represent time Jay Phelps | @_jayphelps debounce, throttle, buffer, combineLatest
  • 60. Observables are lazy Jay Phelps | @_jayphelps retry, repeat
  • 61. Jay Phelps | @_jayphelps Observables can represent just about anything
  • 62. Jay Phelps | @_jayphelps Let’s combine RxJS and Redux!
  • 63. Jay Phelps | @_jayphelps
  • 64.
  • 65. Side effect management for redux, using Epics
  • 66. 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
  • 67. Jay Phelps | @_jayphelps “actions in, actions out”
  • 71. An Epic Jay Phelps | @_jayphelps const pingPongEpic = (action$, store) => action$.ofType('PING') .delay(1000) // <— that's it .map(action => ({ type: 'PONG' }));
  • 72. Jay Phelps | @_jayphelps const isPinging = (state = false, action) => { switch (action.type) { case 'PING': return true; case 'PONG': return false; default: return state; } };
  • 74. Jay Phelps | @_jayphelps Debounced increment / decrement button
  • 75. Jay Phelps | @_jayphelps const counter = (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } };
  • 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. 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' }));
  • 78. Jay Phelps | @_jayphelps Those are contrived examples, obviously
  • 79. Jay Phelps | @_jayphelps Warning: non-trivial examples ahead, don’t struggle to read them entirely
  • 80. Jay Phelps | @_jayphelps Auto-complete
  • 81. 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
  • 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 })) );
  • 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 })) .catch(payload => [{ type: 'QUERY_REJECTED', error: true, payload }]) );
  • 84. 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 }]) );
  • 85. Jay Phelps | @_jayphelps OK, show me really non-trivial examples
  • 86. Jay Phelps | @_jayphelps Bidirectional, multiplexed Web Sockets
  • 87. 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; } }
  • 88. Jay Phelps | @_jayphelps Too much code
  • 89. 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 })) );
  • 90. 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
  • 91. But… Jay Phelps | @_jayphelps
  • 92. Jay Phelps | @_jayphelps You should probably know redux and RxJS in advance
  • 93. Jay Phelps | @_jayphelps RxJS has a bit of a learning curve
  • 94. Jay Phelps | @_jayphelps “Reactive Programming”
  • 95. Co-author Jay Phelps | @_jayphelps Ben Lesh Senior UI Engineer | @benlesh
  • 96. Jay Phelps | @_jayphelps https://redux-observable.js.org
  • 97.