Protocols

The following protocols are available globally.

  • Async action this type of action is intercepted by AsyncMiddleware and is not dispatched to the reducer.

    Recepie to use AsyncAction

    1. Create an AsyncAction action
    2. In the block passed at init. Perform any operation (dispatching it on your queue)
    3. When result is ready, call dispatch passing a new action

    If the AsyncMiddleware receives an AsyncAction it does the following:

    1. Call action.execute passing in the dispatch and get state functions
    2. Stops the action from propagating to other middlewares and reducers

    Example

    Performing an async loading from disk

    struct MyDiskAsyncAction: AsyncAction {
    
      func execute(getState: @escaping GetStateFunction, dispatch: @escaping DispatchFunction) {
        // Perform some work in a background thread
        DispatchQueue(label: "MyQueue").async {
          // Load from disk
          // Process loaded
          // Do more work
    
          // Maybe consult the current state
          let currentState = api.state
    
          // At a latter time dont forget to dispatch
          dispatch(DataLoadedAction(data: data))
        }
    }
    
    store.dispatch(action: MyDiskAsyncAction())
    

    Performing an async network request

    struct MyURLAsyncAction: AsyncAction {
    
      func execute(getState: @escaping GetStateFunction, dispatch: @escaping DispatchFunction) {
        // First dispatch some action syncrhonously
        dispatch(SomeAction(...))
    
        let session = URLSession(configuration: .default)
        // perform a dataTask
        session.dataTask(with: urlRequest) { data, response, error in
    
          if let data = data {
            // Do something with the data
             dispatch(RequestSucceeded(data: data))
    
          } else if let error = error {
    
             // Error happenend
             dispatch(RequestFaile(data: data))
          }
       }
    }
    
    store.dispatch(action: MyURLAsyncAction())
    
    See more

    Declaration

    Swift

    public protocol AsyncAction: Action
  • Protocol used by EqualsFilter filter callback to compare two state values. If your state implements the Equatable protocol there is no code required to implement SuasDynamicEquatable

    Example

    Implement SuasDynamicEquatable manually

    struct MyState: SuasDynamicEquatable {
      let value: Int
    
      func isEqual(to other: Any) -> Bool {
        // Cast to same type
        guard let other = other as? MyState else { return false }
    
        // Compare values
        return other.value == self.value
      }
    }
    

    Implementing SuasDynamicEquatable as an extension

    If your type implement equatable

    struct MyState: Equatable {
      let value: Int
      static func ==(lhs: MyState, rhs: MyState) -> Bool { ... }
    }
    

    You dont need to implement SuasDynamicEquatable just add it as an extension to MyState. No extra code needed.

    extension MyState: SuasDynamicEquatable { }
    
    See more

    Declaration

    Swift

    public protocol SuasDynamicEquatable
  • Protocol that represents a reducer

    Example

    struct MyReducer: Reducer {
      var initialState: Int = 1
    
      func reduce(state: Int, action: Action) -> Int? {
    
        // Cast the action to a specific action
        if let action = action as? SomeAction {
          // state changed, listeners will be notified
          return state + 1
        }
    
        // returning nil means the state did not change and listeners wont be notified
        return nil
      }
    }
    

    Note: Returning nil from reduce signifies that the state did not change which will not inform the listeners.

    See more

    Declaration

    Swift

    public protocol Reducer
  • Action to dispatch to the store

    Example

    struct ButtonTappedAction: Action { }
    
    store.dispatch(action: ButtonTappedAction())
    

    Declaration

    Swift

    public protocol Action
  • Middleware protocol that represents a suas store middleware A middleware helps extending the dispatch logic of Suas.

    A middleware can be used to implement:

    • Logging that logs the state before and after the reducer changes it
    • Perform async network calls and dispatches actions representing the result when the network returns.
    • Other advanced usages…

    Example

    Implementing a logging middleware.

    class LoggerMiddleware: Middleware {
      var api: MiddlewareAPI?
      var next: DispatchFunction?
    
      func onAction(action: Action, getState: @escaping GetStateFunction, dispatch: @escaping DispatchFunction, next: @escaping NextFunction) {
        // Read the state before any reducer changes it
        print("The old state is \(getState())")
    
        // Print the action
        print("The action is \(action)")
    
        // Continue the dispatching process..until the reducer reduces the action
        // Not calling `next` will prevent the action from reaching the reducer
        next?(action)
    
        // Read the state after any reducer changes it
        print("The new state is \(api?.state)")
      }
    }
    
    See more

    Declaration

    Swift

    public protocol Middleware