Introduction to Reactive
Programming with React
Gregory Shehet
• Software Engineer at
• Front-End Digest on
• Software Engineer at
• Front-End Digest on
• Mob-X contributor
Gregory Shehet
@AGambit95
Grammarly
Introduction to Reactive
Programming with React
React
🌟AWESOME🌟
Try to code something
😡 Pain 😡
Update state of
React App
Architecture? 😮
In the Front-End World? 🌍
Really
🌟AWESOME🌟
But…
React is not Reactive
!==
🚀Not about real reactive 🚀
‼Later‼
What is Reactive UI?
let	name	=	'Gregory'	

		

const	App	=	()	=>	{	
		<div>{	name	}</div>	
}	

		

What is Reactive UI?
let	name	=	'Gregory'	

		

const	App	=	()	=>	{	
		<div>{	name	}</div>	
}	

		

name	=	'Ignat'
What is Reactive UI?
let	name	=	observable('Gregory')	

		

const	App	=	()	=>	observer(()	=>		

		<div>{	name	}</div>	

)	

		

name	=	'Ignat'
✨ But a lot of Magic ✨
Treasure hunt in the land of
Reactive frameworks
https://youtu.be/muZG_sQLIG4 👍
• React for UI
• Logs actions
• Observable
• Observables + React = Reactive View
Conclusion: Back to React
What next?
Why am I here?
Focal
Type safe, expressive and composable state
management for React applications.
Sergey Yavnyi
@blacktaxi
• React for UI
• Logs actions
• Observable
• Observables + React = Reactive View
Why Focal?
• React for UI
• Logs actions (subscribe + devtool will be soon)
• Observable
• Observables + React = Reactive View
Why Focal?
And…
• React for UI
• Logs Actions
• Observable (Atom and Lens)
• Observables + React = Reactive View
• Type Safe
• Power of Rx.JS
• React utils
Why Focal?
Type safe 👌
https://staltz.com/all-js-libraries-should-be-authored-in-typescript.html
Why TypeScript?
• Better documentation
• Better autocomplete
• More reliable libraries
• Typed programming matters
What about FRP?
What about FRP?
What is FRP?
What is most important
in our applications?
Any ideas?
What is most important
in our applications?
Events
What is FRP?
Functional reactive programming (FRP) is a
programming paradigm for reactive programming
(asynchronous dataflow programming) using the
building blocks of functional programming (e.g. map,
reduce, filter).
@ Wikipedia
What is FRP?
Functional reactive programming (FRP) is a
programming paradigm for reactive programming
(asynchronous dataflow programming) using the
building blocks of functional programming (e.g. map,
reduce, filter).
@ Wikipedia
Captain Obvious: Excel Example
Observables
Excel Example
Streams
A
2
B
1
Streams
A
2
B
Combine Sum
1
Streams
A
2
B
3
Combine Sum
1
C
Streams
A
2 5
B
C
3
Combine Sum
1
Streams
A
2 5
B
6
C
3
Combine Sum
1
Streams
A
2 5
B
6
C
3
Combine Sum
21
Streams
A
2 5
B
76
C
3
Combine Sum
21
Streams
A
2 5
B
76 6
C
3
Combine Sum
2 11
Streams
A
2 5
B
2
76 6
C
33
Combine Sum
2 11
Back to Observable
Rx?☝
😱 Too many operators 😱
Create, Defer, Empty, Never, Throw, From, Interval, Just, Range, Repeat, Start, Timer, Buffer, FlatMap, GroupBy, Map, Scan, Window, Debounce, Distinct, ElementAt, Filter, First, IgnoreElements, Last, Sample,
Skip, SkipLast, Take, TakeLast, And, Then, When, Pattern, Plan, CombineLatest, Join, Merge, StartWith, Switch, Zip, Catch, onError, Retry, onError, Delay, Do, Materialize, Dematerialize, ObserveOn, Serialize,
Subscribe, SubscribeOn, TimeInterval, Timeout, Timestamp, Using, All, Amb, Contains, DefaultIfEmpty, SequenceEqual, SkipUntil, SkipWhile, TakeUntil, TakeWhile, Average, Concat, Count, Max, Min, Reduce,
Sum, Connect, Publish, RefCount, Replay, To, Action, Callable, Runnable, Array, Iterable, Pattern, Plan, Notification, Future, Aggregate, All, Amb, ambArray, ambWith, and_, And, Any, apply, as_blocking,
asObservable, AssertEqual, asyncAction, asyncFunc, Average, averageDouble, averageFloat, averageInteger, averageLong, blocking, blockingFirst, blockingForEach, blockingIterable, blockingLast,
blockingLatest, blockingMostRecent, blockingNext, blockingSingle, blockingSubscribe, Buffer, bufferWithCount, bufferWithTime, bufferWithTimeOrCount, byLine, cache, cacheWithInitialCapacity, case, Cast,
Catch, catchError, catchException, collect, collect, Filter, collectInto, CombineLatest, combineLatestDelayError, combineLatestWith, Concat, concat_all, concatAll, concatArray, concatArrayDelayError,
concatArrayEager, concatDelayError, concatEager, concatMap, concatMapDelayError, concatMapEager, concatMapEagerDelayError, concatMapIterable, concatMapObserver, concatMapTo, concatWith,
Connect, connect_forever, cons, Contains, controlled, Count, countLong, Create, cycle, Debounce, decode, DefaultIfEmpty, Defer, deferFuture, Delay, delaySubscription, delayWithSelector, Dematerialize,
Distinct, distinctKey, distinctUntilChanged, distinctUntilKeyChanged, Do, doAction, doAfterTerminate, doOnComplete, doOnCompleted, doOnDispose, doOnEach, doOnError, doOnLifecycle, doOnNext,
doOnRequest, doOnSubscribe, doOnTerminate, doOnUnsubscribe, doseq, doWhile, drop, dropRight, dropUntil, dropWhile, ElementAt, ElementAtOrDefault, Empty, emptyObservable, empty?, encode, ensures,
error, every, exclusive, exists, expand, failWith, Filter, filterNot, Finally, finallyAction, finallyDo, find, findIndex, First, firstElement, FirstOrDefault, firstOrElse, FlatMap, flatMapFirst, flatMapIterable,
flatMapIterableWith, flatMapLatest, flatMapObserver, flatMapWith, flatMapWithMaxConcurrent, flat_map_with_index, flatten, flattenDelayError, foldl, foldLeft, for, forall, ForEach, forEachFuture,
forEachWhile, forIn, forkJoin, From, fromAction, fromArray, FromAsyncPattern, fromCallable, fromCallback, FromEvent, FromEventPattern, fromFunc0, fromFuture, fromIterable, fromIterator, from_list,
fromNodeCallback, fromPromise, fromPublisher, fromRunnable, Generate, generateWithAbsoluteTime, generateWithRelativeTime, generator, GetEnumerator, getIterator, GroupBy, GroupByUntil, GroupJoin,
head, headOption, headOrElse, if, ifThen, IgnoreElements, indexOf, interleave, interpose, Interval, intervalRange, into, isEmpty, items, Join, join, jortSort, jortSortUntil, Just, keep, keep-indexed, Last, lastElement,
lastOption, LastOrDefault, lastOrElse, Latest, latest, Switch, length, let, letBind, lift, limit, LongCount, ManySelect, Map, map, Zip, MapCat, mapCat, Zip, map-indexed, mapTo, mapWithIndex, Materialize, Max,
MaxBy, Merge, mergeAll, mergeArray, mergeArrayDelayError, merge_concurrent, mergeDelayError, mergeObservable, mergeWith, Min, MinBy, MostRecent, Multicast, multicastWithSelector, nest, Never,
Next, Next, none, nonEmpty, nth, ObserveOn, ObserveOnDispatcher, observeSingleOn, of, of_array, ofArrayChanges, of_enumerable, of_enumerator, ofObjectChanges, OfType, ofWithScheduler,
onBackpressureBlock, onBackpressureBuffer, onBackpressureDrop, OnErrorResumeNext, onErrorReturn, onErrorReturnItem, onExceptionResumeNext, onTerminateDetach, orElse, pairs, pairwise, partition,
partition-all, pausable, pausableBuffered, pluck, product, Publish, PublishLast, publish_synchronized, publishValue, raise_error, Range, Reduce, reduceWith, reductions, RefCount, Repeat, repeat_infinitely,
repeatUntil, repeatWhen, Replay, rescue_error, rest, Retry, retry_infinitely, retryUntil, retryWhen, Return, returnElement, returnValue, runAsync, safeSubscribe, Sample, Scan, scanWith, scope, Select, Map,
select, Filter, selectConcat, selectConcatObserver, SelectMany, selectManyObserver, select_switch, selectSwitch, selectSwitchFirst, selectWithMaxConcurrent, select_with_index, seq, SequenceEqual,
sequence_eql?, SequenceEqualWith, Serialize, share, shareReplay, shareValue, Single, singleElement, SingleOrDefault, singleOption, singleOrElse, size, Skip, SkipLast, skipLastWithTime, SkipUntil,
skipUntilWithTime, SkipWhile, skipWhileWithIndex, skip_with_time, slice, sliding, slidingBuffer, some, sort, sorted, sort-by, sorted-list-by, split, split-with, Start, startAsync, startFuture, StartWith,
startWithArray, stringConcat, stopAndWait, subscribe, subscribeActual, SubscribeOn, SubscribeOnDispatcher, subscribeOnCompleted, subscribeOnError, subscribeOnNext, subscribeWith, Sum, sumDouble,
sumFloat, sumInteger, sumLong, Switch, switchCase, switchIfEmpty, switchLatest, switchMap, switchMapDelayError, switchOnNext, switchOnNextDelayError, Synchronize, Take, take_with_time, takeFirst,
TakeLast, takeLastBuffer, takeLastBufferWithTime, takeLastWithTime, takeRight, TakeLast, TakeUntil, takeUntilWithTime, TakeWhile, takeWhileWithIndex, tail, tap, tapOnCompleted, tapOnError, tapOnNext,
Then, thenDo, Throttle, throttleFirst, throttleLast, throttleWithSelector, throttleWithTimeout, Throw, throwError, throwException, TimeInterval, Timeout, timeoutWithSelector, Timer, Timestamp, To, to_a,
ToArray, ToAsync, toBlocking, toBuffer, to_dict, ToDictionary, ToEnumerable, ToEvent, ToEventPattern, ToFlowable, ToFuture, to_h, toIndexedSeq, toIterable, toIterator, ToList, ToLookup, toMap, toMultiMap,
ToObservable, toSet, toSortedList, toStream, ToTask, toTraversable, toVector, tumbling, tumblingBuffer, unsafeCreate, unsubscribeOn, Using, When, Where, while, whileDo, Window, windowWithCount,
windowWithTime, windowWithTimeOrCount, windowed, withFilter, withLatestFrom, Zip, zipArray, zipIterable, zipWith, zipWithIndex, ++, +:, :+
Is it not React way? 🤔
Looks like Angular
React-Redux infrastructure
• Redux
• Redux Form
• Redux Thunk or Redux Saga
• Redux React Router
• Reselect
• …
It’s ok
to learn something every day
🍭 It’s fun 🍭
💤 Boring 💤
Talking about Operators is
How to learn? (Video)
1) Holy.js 2016 – Виктор Русакович – Реактивное программирование:
управляем потоками данных
https://youtu.be/3cGKw9sxV_g
2) KharkivJS 2016 — Aliaksei Bahachuk – Reactive Programming with RxJS
https://youtu.be/r1BD4TEL6Yc
How to learn? (Read)
1) http://reactivex.io/rxjs
2) https://www.learnrxjs.io/
3) The introduction to Reactive Programming you've been missing
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
4) Egghead courses (Not Free 🙁)
https://egghead.io/technologies/rx
@andrestaltz
André Staltz
How to learn? (Follow)
Theory is boring
<Let’s code something />
Interval Increment Demo
Observable.interval
Observable	
		.interval(1000)	

1 32 4
interval
5
Observable.interval
Observable	
		.interval(1000)	

1 32 4
interval
5
Problem?
Observable.startWith
Observable	
		.interval(1000)	
		.startWith(0)	

1 32 4
interval
5
1 32 4
startWith
50
Rx is Awesome
But there is too much
pain to use it in our app
How to render
Observables? 🤔
Reactive UI
<F.div>	

		{	

				Observable	

						.interval(1000)	
						.startWith(0)	

		}	

</F.div>	

1 32 4
interval
5
1 32 4
startWith
50
Magic is simple
<F.div>{	Observable	}</F.div>
Let’s stop our increment
Let’s stop our increment
Need Store Status/Value
1 32 4
interval
5
true false true
isRunning
How does it work?
1 32 4
interval
5
true false true
isRunning
How does it work?
Magic
1 32 4
interval
5
1 2
result
3
true false true
isRunning
How does it work?
Magic
Let’s start from store
our result value
.scan is the same as .reduce
[1,	...,	n].reduce(	
		(acc,	curr)	=>	acc	+	curr,		
		0	
)	

Observable.scan
Observable	

		.interval(1000)	
		.startWith(0)

		.scan((acc,	curr)	=>		
				curr,	
				0	
		)
1 32 4
interval
5
1 32 4
startWith
5
1 32 4
scan
50
0
1 32 4
interval
5
1 2
result
3
true false true
isRunning
How it should work
Magic
+1 +1+1 +1
stream of 1 with interval
+1
1 2
result
3
true false true
isRunning
How it should work
Magic
Observable.mapTo
Observable	

		.interval(1000)	
		.mapTo(1)		
		.startWith(0)

		.scan((acc,	curr)	=>		
				acc	+	curr,		
				0	
		)
1 32 4
interval
5
1 11 1
mapTo
1
1 11 1
startWith
1
1 32 4
scan
50
0
Update .scan
Observable	

		.interval(1000)	
		.mapTo(1)		
		.startWith(0)

		.scan((acc,	curr)	=>		
				acc	+	curr,		
				0	
		)
1 32 4
interval
5
1 11 1
mapTo
1
1 11 1
startWith
1
1 32 4
scan
50
0
How to store our
observables? 🤔
Our application
App
Increment
Our application
App
const	App	=	{		

		increment:	{		

				isRunning:	true	

				...		

		}	

		...	

}	

Increment
Our application
App
Increment
const	App	=	{		

		increment:	{		

				isRunning:	true,	
				value:	0

				...		

		}	

		...	

}	

Atom
const	app	=	Atom({	increment:	{	isRunning:	true	}	})	

		

app.get()	

//	app:	{	increment:	{	isRunning:	true	}	}	

		

const	increment	=	app.lens(x	=>	x.increment)	//	Atom	

increment.set({	isRunning:	false	})	

//	increment:	{	isRunning:	false	}	}	

//	app:	{	increment:	{	isRunning:	false	}	}	
app.view(x	=>	x.increment)	//	ReadOnlyAtom

		

increment.lens(x	=>	x.isRunning).modify(x	=>	!x)	

//	increment:	{	isRunning:	true	}	}			

//	{	increment:	{	isRunning:	true	}	}	

Atom .get()/set()
const	app	=	Atom({	increment:	{	isRunning:	true	}	})	

		

app.get()	

//	app:	{	increment:	{	isRunning:	true	}	}	

		

const	increment	=	app.lens(x	=>	x.increment)	//	Atom	

increment.set({	isRunning:	false	})	

//	increment:	{	isRunning:	false	}	}	

//	app:	{	increment:	{	isRunning:	false	}	}	
app.view(x	=>	x.increment)	//	ReadOnlyAtom	

		

increment.lens(x	=>	x.isRunning).modify(x	=>	!x)	

//	increment:	{	isRunning:	true	}	}			

//	{	increment:	{	isRunning:	true	}	}	

Lens/View
const	app	=	Atom({	increment:	{	isRunning:	true	}	})	

		

app.get()	

//	app:	{	increment:	{	isRunning:	true	}	}	

		

const	increment	=	app.lens(x	=>	x.increment)	//	Atom	

increment.set({	isRunning:	false	})	

//	increment:	{	isRunning:	false	}	}	

//	app:	{	increment:	{	isRunning:	false	}	}		
app.view(x	=>	x.increment)	//	ReadOnlyAtom

		

increment.lens(x	=>	x.isRunning).modify(x	=>	!x)	

//	increment:	{	isRunning:	true	}	}			

//	{	increment:	{	isRunning:	true	}	}	

Atom .modify()
const	app	=	Atom({	increment:	{	isRunning:	true	}	})	

		

app.get()	

//	app:	{	increment:	{	isRunning:	true	}	}	



const	increment	=	app.lens(x	=>	x.increment)	//	Atom	

increment.set({	isRunning:	false	})	

//	increment:	{	isRunning:	false	}	}	

//	app:	{	increment:	{	isRunning:	false	}	}	
app.view(x	=>	x.increment)	//	ReadOnlyAtom

		

increment.lens(x	=>	x.isRunning).modify(x	=>	!x)	

//	increment:	{	isRunning:	true	}	}			

//	{	increment:	{	isRunning:	true	}	}	

Why Atoms and Lenses?
App
Increment
Increment with Stop Demo
1 32 4
interval
5
1 2
result
3
true false true
isRunning
How it should work
Magic
How to combine two
Observables?
Observable.switchMap
Observable.combineLatest
Stream of 1 with .interval and .mapTo
Observable	

		.interval(1000)	
		.mapTo(1)		
		.startWith(0)

		.scan((acc,	curr)	=>		
				acc	+	curr,		
				0	
		)
1 32 4
interval
5
1 11 1
mapTo
1
1 11 1
startWith
1
1 32 4
scan
50
0
.combineLatest 1 32 4
interval
5
1 11 1
mapTo
1
1
startWith
1 2
scan
0
Observable	

		.combineLatest(	

				Observable	

					.interval(1000)		
					.mapTo(1)	
					.startWith(0),	

				increment.view(x	=>	x.isRunning)	

		)	

		.scan((acc,	[curr,	isRunning])	=>		

				isRunning	?	acc	+	curr	:	acc,	0	

		)	

false true
isRunning
true
combineLatest
1 11 1 10
How does it work? 1 32 4
interval
5
1 11 1
mapTo
1
1
startWith
1 2
scan
0
Observable	

		.combineLatest(	

				Observable	

					.interval(1000)		
					.mapTo(1)	
					.startWith(0),	

				increment.view(x	=>	x.isRunning)	

		)	

		.scan((acc,	[curr,	isRunning])	=>		

				isRunning	?	acc	+	curr	:	acc,	0	

		)	

false true
isRunning
true
combineLatest
1 11 1 10
How does it work? 1 32 4
interval
5
1 11 1
mapTo
1
1
startWith
1 2
scan
0
Observable	

		.combineLatest(	

				Observable	

					.interval(1000)		
					.mapTo(1)	
					.startWith(0),	

				increment.view(x	=>	x.isRunning)	

		)	

		.scan((acc,	[curr,	isRunning])	=>		

				isRunning	?	acc	+	curr	:	acc,	0	

		)	

false true
isRunning
true
combineLatest
1 11 1 10
How does it work? 1 32 4
interval
5
1 11 1
mapTo
1
1
startWith
1 2
scan
0
Observable	

		.combineLatest(	

				Observable	

					.interval(1000)		
					.mapTo(1)	
					.startWith(0),	

				increment.view(x	=>	x.isRunning)	

		)	

		.scan((acc,	[curr,	isRunning])	=>		

				isRunning	?	acc	+	curr	:	acc,	0	

		)	

false true
isRunning
true
combineLatest
1 11 1 10
How does it work? 1 32 4
interval
5
1 11 1
mapTo
1
1
startWith
1 2
scan
0
Observable	

		.combineLatest(	

				Observable	

					.interval(1000)		
					.mapTo(1)	
					.startWith(0),	

				increment.view(x	=>	x.isRunning)	

		)	

		.scan((acc,	[curr,	isRunning])	=>		

				isRunning	?	acc	+	curr	:	acc,	0	

		)	

false true
isRunning
true
combineLatest
1 11 1 10
.switchMap
Another solution with
.mapTo to .switchMap
Observable	

		.interval(1000)	
		.mapTo(1)		
		.startWith(0)

		.scan((acc,	curr)	=>		
				acc	+	curr,		
				0	
		)
1 32 4
interval
5
1 11 1
mapTo
1
1 32 4
startWith
5
1 32 4
scan
50
0
.mapTo
1 32 4
interval
5
1 11 1
mapTo
1
1 11 1
startWith
1
1 32 4
scan
50
0
.switchMap
1 32 4
interval
5
1 00 0
mapTo
1
switchMap
1 2
scan
0
false true
isRunning
true
Observable	

			.interval(1000)		
			.startWith(0)

			.switchMap(()	=>		

					increment.view(x	=>	x.isRunning	?	1	:	0)	

			)	

			.scan((acc,	curr)	=>	acc	+	curr,	0)
Store our value
App
Increment
const	App	=	{		

		increment:	{		

				isRunning:	true,	
				value:	0

				...		

		}	

		...	

}	

//	componentDidMount	
const	value	=	increment.lens(x	=>	x.value)	
Observable	

			.interval(1000)	

			.startWith(0)	

			.switchMap(()	=>		

					increment.view(x	=>	x.isRunning	?	1	:	0)	

			)	

			.subscribe(x	=>	value.modify(v	=>	v	+	x))
//	render	
const	value	=	increment.view(x	=>	x.value)
<F.div>{	value	}</F.div>	

//	componentDidMount	
const	value	=	increment.lens(x	=>	x.value)	
Observable	

			.interval(1000)	

			.startWith(0)	

			.switchMap(()	=>		

					increment.view(x	=>	x.isRunning	?	1	:	0)	

			)	

			.subscribe(x	=>	value.modify(v	=>	v	+	x))
//	render	
const	value	=	increment.view(x	=>	x.value)
<F.div>{	value	}</F.div>	

//	componentDidMount	
const	value	=	increment.lens(x	=>	x.value)
Observable	

			.interval(1000)	

			.startWith(0)	

			.switchMap(()	=>		

					increment.view(x	=>	x.isRunning	?	1	:	0)	

			)	

			.subscribe(x	=>	value.modify(v	=>	v	+	x))
//	render	
const	value	=	increment.view(x	=>	x.value)
<F.div>{	value	}</F.div>	

Observable	

			.interval(1000)	

			.startWith(0)	

			.switchMap(()	=>		

					increment.view(x	=>	x.isRunning	?	1	:	0)	

			)	

			.subscribe(x	=>	value.modify(v	=>	v	+	x))
What’s wrong with this code?
Observable	

			.interval(1000)	

			.startWith(0)	

			.switchMap(()	=>		

					increment.view(x	=>	x.isRunning	?	1	:	0)	

			)	

			.subscribe(x	=>	value.modify(v	=>	v	+	x))
A little clue. Do you have any ideas?
Profiling
Observable	

			.interval(1000)	

			.startWith(0)	

			.switchMap(()	=>		

					increment.view(x	=>	x.isRunning	?	1	:	0)	

			)	

			.subscribe(x	=>	value.modify(v	=>	v	+	x))
So any ideas?
increment.switchMap(x	=>		

		x.isRunning		

		?	Observable.interval(1000).mapTo(1).startWith(0)	

		:	Observable.of(0)	

)	
.subscribe(x	=>	value.modify(v	=>	v	+	x))	

Return appropriate Observable
Don’t forget to unsubscribe :)
//	componentDidMount()	

		

const	unsubscribe	=	Observable	

		...	

		.subscribe(x	=>	...)	

		

//	componentWillUnmount()	

		

unsubscribe()	

Homework
Create timer!
Really
🌟AWESOME🌟
Reactive Components
🌟Awesome🌟
But what about existing components?🤔
Styled-components
Styled-Component
const	Box	=	styled.div`	

		padding:	20px;	

		width:	${props	=>	props.width}px;	

		background:	${props	=>	props.color};	

`	

		

const	App	=	props	=>	{	

		const	color	=	...

		const	width	=	...

		return	(	

				<Box	color={color}	width={width}>	

						...	

				</Box>	

		)	

}	

const	Box	=	styled.div`	

		padding:	20px;	

		width:	${props	=>	props.width}px;	

		background:	${props	=>	props.color};	

`	

		

const	App	=	props	=>	{	

		const	color	=	...

		const	width	=	...

		return	(	

				<Box	color={color}	width={width}>	

						...	

				</Box>	

		)	

}	

Styled-Component
Atom props
const	Box	=	styled.div`	

		padding:	20px;	

		width:	${props	=>	props.width}px;	

		background:	${props	=>	props.color};	

`	

		

const	App	=	props	=>	{	

		const	color	=	props.state.lens(x	=>	x.color)	

		const	width	=	props.state.lens(x	=>	x.width)	

		return	(	

				<Box	color={color}	width={width}>	

						...	

				</Box>	

		)	

}	

Lift Component
const	Box	=	lift(styled.div`	

		padding:	20px;	

		width:	${props	=>	props.width}px;	

		background:	${props	=>	props.color};	

`)	

		

const	App	=	props	=>	{	

		const	color	=	props.state.lens(x	=>	x.color)	

		const	width	=	props.state.lens(x	=>	x.width)	

		return	(	

				<Box	color={color}	width={width}>	

						...	

				</Box>	

		)	

}	

Lift Styled-component
History Util in Examples
Magic of Observables
https://github.com/grammarly/focal/blob/master/examples/all/src/utils/history.ts
Production Ready
More than 18 million users!
What next?
• Devtool
• Decouple: Focal and Focal React
• Workshop
• …
Plans
Part 2
Reactive State Management
App
Some widget
Share and Star🙏
https://github.com/grammarly/focal
yarn add @grammarly/focal
Thank you!
Questions are welcome
@AGambit95
April 26 2017
Style your application with CSS in JS
https://www.facebook.com/events/2269571779934837/

Григорий Шехет "Introduction in Reactive Programming with React"