unidirectional data flow with reactor
TRANSCRIPT
![Page 1: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/1.jpg)
UNIDIRECTIONAL DATA FLOWWITH REACTOR
![Page 2: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/2.jpg)
WHAT IS THE STATE OF YOUR APP?
![Page 3: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/3.jpg)
WHERE DOES STATE LIVE?
![Page 4: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/4.jpg)
WHAT DOES STATE LOOK LIKE?
![Page 5: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/5.jpg)
STATEstruct Player: State { var name: String var level: Int}
![Page 6: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/6.jpg)
STATE COMPOSITIONstruct RPGState { var players: Player var monsters: Monsters
// ...}
![Page 7: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/7.jpg)
CHANGING STATEDATA FLOW
![Page 8: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/8.jpg)
▸ Delegates▸ Target-Actions▸ Completion Blocks▸ Notification Center
▸ KVO▸ Segues▸ didSet
▸ NSFetchedResultsController
![Page 9: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/9.jpg)
WHAT DIRECTION IS THE DATA FLOWING?
![Page 10: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/10.jpg)
SPOT THE BUG!class ViewController: UIViewController { @IBOutlet var titleLabel: UILabel!
var name: String? { didSet { titleLabel.text = name } }}
![Page 11: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/11.jpg)
SPOT THE NEW BUG!class ViewController: UIViewController { @IBOutlet var titleLabel: UILabel?
var name: String? { didSet { titleLabel?.text = name } }}
![Page 12: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/12.jpg)
THE IMPLICITLY UNWRAPPED OPTIONAL DANCEclass ViewController: UIViewController { @IBOutlet var titleLabel: UILabel?
var name: String? { didSet { configureView() } }
func configureView() { titleLabel?.text = name }
override func viewDidLoad() { super.viewDidLoad() configure() }}
![Page 13: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/13.jpg)
PROBLEM: UNDEFINED DATA
FLOW
![Page 14: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/14.jpg)
SINGLE SOURCE OF TRUTH™
![Page 15: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/15.jpg)
(STATE) → VIEWUI AS A PURE FUNCTION OF STATE
![Page 16: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/16.jpg)
REDRAW VIEW ON EVERY STATE CHANGE?!?!?
![Page 17: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/17.jpg)
REACT✨ VIRTUAL DOM ✨
![Page 18: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/18.jpg)
!UIKIT
![Page 19: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/19.jpg)
(STATE) → VOIDWITH SIDE EFFECTS
![Page 20: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/20.jpg)
extension ViewController { func update(with state: State) { nameLabel.text = state.name }}
![Page 21: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/21.jpg)
UNIDIRECTIONAL DATA FLOWALL UPDATES FLOW IN SAME DIRECTION
![Page 22: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/22.jpg)
JARSEN/REACTOR
![Page 23: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/23.jpg)
![Page 24: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/24.jpg)
CORE▸ Holds the Single Source of Truth™▸ Only the Core can change the state
▸ Notifies all subscribers with state changes
![Page 25: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/25.jpg)
OBSERVING STATEclass ViewController: core.Subscriber { var core = App.sharedCore @IBOutlet var nameLabel: UILabel!
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) core.add(subscriber: self) }
override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) core.remove(subscriber: self) }
func update(with state: State) { nameLabel.text = state.name }}
![Page 26: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/26.jpg)
UPDATING STATEstruct Increment: Event {}
extension ViewController { @IBAction func didPressIncrement() { core.fire(event: Increment()) }}
![Page 27: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/27.jpg)
ASYNC EVENTSstruct Update<T>: Event { var value: T}
struct GetUsers: Command { func execute(state: State, core: Core<State>) { myNetworkThing.get("users") { json in // transform to user object, using Marshal, of course core.fire(event: Update(value: users)) } }}
![Page 28: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/28.jpg)
ASYNC EVENTSextension ViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) core.add(subscriber: self) core.fire(command: GetUsers()) }}
![Page 29: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/29.jpg)
HOW DO EVENTS UPDATE STATE?struct Player: State { var name: String var level: Int
mutating func react(to event: Event) { switch event { case let _ as LevelUp: level += 1 default: break } }}
![Page 30: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/30.jpg)
HOW DO EVENTS UPDATE COMPOSED STATES?struct RPGState: State { var player: Player var monsters: Monsters
mutating func react(to event: Event) { player.react(to: event) monsters.react(to: event) }}
![Page 31: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/31.jpg)
MIDDLEWAREGood for side effects like logging, analytics, displaying errors...
struct LoggingMiddleware: Middleware { func process(event: Event, state: State) { switch event { case _ as LevelUp: print("Leveled Up!") default: break } }}
![Page 32: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/32.jpg)
HOT RELOADINGUSING MARSHAL + KZFILEWATCHER
![Page 33: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/33.jpg)
![Page 34: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/34.jpg)
OPTIMISTIC NETWORK RESULTS
![Page 35: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/35.jpg)
TIME TRAVEL
![Page 36: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/36.jpg)
STATE RESTORATION
![Page 37: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/37.jpg)
PERFORMANCE CONCERNS
![Page 38: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/38.jpg)
Don't like the API? ☹Don't like 3rd Party? "
ROLL YOUR OWN !It's a straightforward, not-too-novel pattern.
![Page 39: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/39.jpg)
NAVIGATION STATE / ROUTING
![Page 40: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/40.jpg)
REACTOR RESOURCES▸ React Native, Native
▸ Optimistic Networking with Reactor
![Page 41: Unidirectional Data Flow with Reactor](https://reader030.vdocuments.mx/reader030/viewer/2022020213/58729ecc1a28ab07208b546d/html5/thumbnails/41.jpg)
OTHER RESOURCES▸ A composable pattern for pure state machines with effects by Andy
Matuschak▸ Unidirectional Data Flow in Swift by Benjamin Encz
▸ Elmification of Swift▸ MCV-N Swift Talk by Marcus Zarra
▸ Backend-driven Native UIs by John Sundell