A video series exploring functional programming and Swift.
#75 • Monday Oct 7, 2019 • Subscriber-only

Modular State Management: The Point

We’ve now fully modularized our app by extracting its reducers and views into their own modules. Each screen of our app can be run as a little app on its own so that we can test its functionality, all without needing to know how it’s plugged into the app as a whole. And this is the point of modular state management!

This episode builds on concepts introduced previously:

#75 • Monday Oct 7, 2019 • Subscriber-only

Modular State Management: The Point

We’ve now fully modularized our app by extracting its reducers and views into their own modules. Each screen of our app can be run as a little app on its own so that we can test its functionality, all without needing to know how it’s plugged into the app as a whole. And this is the point of modular state management!

This episode builds on concepts introduced previously:


Subscribe to Point‑Free

This episode is for subscribers only. To access it, and all past and future episodes, become a subscriber today!

See subscription optionsorLog in

Sign up for our weekly newsletter to be notified of new episodes, and unlock access to any subscriber-only episode of your choosing!

Sign up for free episode

Introduction

Alright, we’ve now accomplished what we set out to do at the beginning of this series of episodes on modular state management. First, we defined what “modular” meant: we determined that modularity was the ability to move code into a literal Swift module so that it is completely isolated from the rest of your app. Then we showed just how modular our reducers already were by breaking each one off into a framework of its own. Finally, in order to modularize our views we discovered two forms of composition on the Store type: one that allowed us to focus an existing store on some subset of state, and another that allowed us to focus an existing store on some subset of actions. These operations allowed us to separate all of our views from more global, app-level concerns and move them into isolated modules of their own.

Subscribe to Point-Free

👋 Hey there! Does this episode sound interesting? Well, then you may want to subscribe so that you get access to this episodes and more!


Exercises

  1. So far it has been very easy to tap into SwiftUI’s button actions in order to send those actions to the store. However, not all SwiftUI actions are that easy. For instance, TextFields do not expose closures for us to implement that will be notified when text is changed in the field. Instead, they use Binding<String> values, which are 2-way bindings that allow you to simulataneously change the text field’s value and observe text field changes.

    This model unfortauntely does not fit our architecture since we prefer all mutations of state go through our store and reducer. However, it’s easy to fix! Implement the following function on Store, which allows you to construct a Binding by providing a way to construct an Action from the binding value and a way to extract a binding value from our store’s value:

    extension Store {
      public func send<LocalValue>(
        _ event: @escaping (LocalValue) -> Action,
        binding keyPath: KeyPath<Value, LocalValue>
      ) -> Binding<LocalValue> {
        fatalError("Unimplemented")
      }
    }
    

    We have decided to call this method send so that it mimics the standard send method on Store. This means that you can simply search for store.send in your application to find all places where user actions feed into the architecture.

  2. Using the send implementation from the previous exercise, change the Text view that holds the counter into a TextField, which would allow the user to enter any number they want. To accomplish this you will need to introduce a new counter action counterTextFieldChanged(String) in order to be notified when the user types into the field.


References

Chapters
Introduction
00:05
What’s the point?
01:24
The favorite primes app
04:01
The prime modal app
06:24
The counter app
07:45
Fixing the root app
13:25
Conclusion
18:07