登录状态管理

我们重新走下流程 😄,用 纯函数 做状态管理:

typealias UserID = String

enum LoginError: Error, Equatable {
    case usernamePasswordMismatch
    case offline
}

//首先,我们得有个状态
struct State: Equatable {

    var username: String    // 输入的用户名
    var password: String    // 输入的密码

    var loading: Bool         // 登录中
    var data: UserID?        // 登录成功
    var error: LoginError?  // 登录失败

   //然后,我们要有各种事件
    enum Event {
        case onUpateUsername(String)
        case onUpatePassword(String)
        case onTriggerLogin
        case onLoginSuccess(UserID)
        case onLoginError(LoginError)
    }

    //最后,我们要有一个 纯函数 来管理我们的状态
    static func reduce(_ state: State, event: Event) -> State {
        var newState = state
        switch event {
        case .onUpateUsername(let username):
            newState.username = username
        case .onUpatePassword(let password):
            newState.password = password
        case .onTriggerLogin:
            newState.loading = true
            newState.data = nil
            newState.error = nil
        case .onLoginSuccess(let userId):
            newState.loading = false
            newState.data = userId
        case .onLoginError(let error):
            newState.loading = false
            newState.error = error
        }
        return newState
    }
}

现在我们可以在测试环境模拟各种事件,并且判断结果是否符合预期:


//更新用户名事件
func testOnUpateUsername() {
    
    let state = State(username: "",password: "",loading: false,data: nil,error: nil)
    
    let newState = State.reduce(state, event: .onUpateUsername("beeth0ven"))
    
    let expect = State(username: "beeth0ven",password: "",loading: false,data: nil,error: nil)
    
    newState == expect // 结果:true 😎
}
//更新密码事件
func testOnUpatePassword() {
    
    let state = State(username: "beeth0ven",password: "",loading: false,data: nil,error: nil)
    
    let newState = State.reduce(state, event: .onUpatePassword("123456"))
    
    let expect = State(username: "beeth0ven",password: "123456",loading: false,data: nil,error: nil)
    
    newState == expect // 结果:true 😎
}
//触发登录事件
func testOnTriggerLogin() {
    
    let state = State(username: "beeth0ven",password: "123456",loading: false,data: nil,error: nil)
    
    let newState = State.reduce(state, event: .onTriggerLogin)
    
    let expect = State(username: "beeth0ven",password: "123456",loading: true,data: nil,error: nil)
    
    newState == expect // 结果:true 😎
}
//登录成功事件
func testOnLoginSuccess() {
    
    let state = State(username: "beeth0ven",password: "123456",loading: true,data: nil,error: nil)
    
    let newState = State.reduce(state, event: .onLoginSuccess("userID007"))
    
    let expect = State(username: "beeth0ven",password: "123456",loading: false,data: "userID007",error: nil)
    
    newState == expect // 结果:true 😎
}
//登录失败事件
func testOnLoginError() {
    
    let state = State(username: "beeth0ven",password: "123456",loading: true,data: nil,error: nil)
    
    let newState = State.reduce(state, event: .onLoginError(.usernamePasswordMismatch))
    
    let expect = State(username: "beeth0ven",password: "123456",loading: false,data: nil,error: .usernamePasswordMismatch)
    
    newState == expect // 结果:true 😎
}


这样我们可以轻易掌控程序的运行状态,以及各种状态更新。

现在,我们知道如何用 纯函数 做状态管理了。不过当前的代码形态,离投入生产环境,还存在好几个过度形态。这些过度形态有的是围绕如何引入 附加作用,而做了一些应用架构。

在这个问题上,不同地架构也提出了不同的解决方案,如:RxFeedbackfeedbackLoop 引入 附加作用,Reduxmiddleware 引入 附加作用 等等。这里就不一一介绍了,这些库的官方网站都会有相关说明。

最后,我们还是将代码演化到下一个形态,这里我选择使用 Redux 流派。因为个人的觉得他的知识依赖要少一些,可以让更多读者从中获益。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容