{"id":18264763,"url":"https://github.com/reactcomponentkit/bkredux","last_synced_at":"2025-07-08T06:41:31.408Z","repository":{"id":56902960,"uuid":"142728966","full_name":"ReactComponentKit/BKRedux","owner":"ReactComponentKit","description":"BKRedux is implementation of Redux store in Swift.","archived":false,"fork":false,"pushed_at":"2019-05-25T07:24:37.000Z","size":897,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-12T21:03:00.383Z","etag":null,"topics":["redux","swift"],"latest_commit_sha":null,"homepage":"https://github.com/ReactComponentKit/BKRedux","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ReactComponentKit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-29T03:52:21.000Z","updated_at":"2019-05-25T07:22:04.000Z","dependencies_parsed_at":"2022-08-21T01:50:57.424Z","dependency_job_id":null,"html_url":"https://github.com/ReactComponentKit/BKRedux","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/ReactComponentKit/BKRedux","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FBKRedux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FBKRedux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FBKRedux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FBKRedux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ReactComponentKit","download_url":"https://codeload.github.com/ReactComponentKit/BKRedux/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FBKRedux/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264211393,"owners_count":23573503,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["redux","swift"],"created_at":"2024-11-05T11:15:51.089Z","updated_at":"2025-07-08T06:41:31.358Z","avatar_url":"https://github.com/ReactComponentKit.png","language":"Swift","readme":"# BKRedux\n\nBKRedux is implementation of Redux store in Swift. \n\n## How to install\n\n```\npod 'BKRedux'\n```\n\n## Counter Example\n\n![](./art/shot.png)\n\n### Define State\n \nYou should confirm State protocol to define your state.\n\n```swift\nstruct MyState: State {\n    var count: Int = 0\n    var color: UIColor = UIColor.white\n    var error: (Error, Action)? = nil\n}\n```\n\n\n### Deine Actions\n\n```swift\nstruct IncreaseAction: Action {\n    let payload = 1\n}\n\nstruct DecreaseAction: Action {\n    let payload = -1\n}\n\nstruct RandomColorAction: Action {\n    private static let colors = [\n        UIColor.blue,\n        UIColor.yellow,\n        UIColor.red,\n        UIColor.magenta,\n        UIColor.purple,\n        UIColor.brown,\n        UIColor.lightGray,\n        UIColor.white\n    ]\n    \n    let payload: UIColor = RandomColorAction.colors[Int(arc4random()) % RandomColorAction.colors.count]\n}\n```\n\n### Define Reducers\n\n#### Reducer for the count state\n\n```swift\nimport Foundation\nimport RxSwift\n\nfunc countReducer(state: State, action: Action) -\u003e Observable\u003cState\u003e {\n    guard var mutableState = state as? MyState else { return .just(state) }\n        \n    switch action {\n    case let act as IncreaseAction:\n        mutableState.count += act.payload\n    case let act as DecreaseAction:\n        mutableState.count += act.payload\n    default:\n        break\n    }\n    \n    return .just(mutableState)\n}\n```\n\n#### Reducer for the color state\n\n```swift\nimport RxSwift\nimport UIKit\n\nfunc colorReducer(state: State, action: Action) -\u003e Observable\u003cState\u003e {\n    guard var mutableState = state as? MyState else { return .just(state) }\n    \n    if let act = action as? RandomColorAction {\n        mutableState.color = act.payload\n    }\n    return .just(mutableState)\n}\n```\n\n### Define Middlewares if you needed.\n\n#### Console Log Middleware\n\n```swift\nimport Foundation\nimport RxSwift\n\nfunc consoleLogMiddleware(state: State, action: Action) -\u003e Observable\u003cState\u003e {\n    print(\"[## LOGGING ##] action: \\(String(describing: action)) :: state: \\(state)\")\n    return Observable.just(state)\n}\n```\n\n#### Print Cache Value Middleware\n\n```swift\nimport Foundation\nimport RxSwift\n\nfunc printCacheValue(state: State, action: Action) -\u003e Observable\u003cState\u003e {\n    print(\"[## CACHED ##] value: \\(UserDefaults.standard.integer(forKey: \"count\"))\")\n    return  Observable.just(state)\n}\n```\n\n### Define Postwares if you needed.\n\n#### Cache Count Value Postware\n\n```swift\nimport Foundation\nimport RxSwift\n\nfunc cachePostware(state: State, action: Action) -\u003e Observable\u003cState\u003e {\n    return Single.create(subscribe: { (single) -\u003e Disposable in\n        guard let mystate = state as? MyState else {\n            single(.success(state))\n            return Disposables.create()\n        }\n        \n        UserDefaults.standard.set(mystate.count, forKey: \"count\")\n        UserDefaults.standard.synchronize()\n        single(.success(mystate))\n        \n        return Disposables.create()\n    }).asObservable()\n}\n```\n\n### Make ViewModel if you needed.\n\nBKRedux provides ViewModelType for MVVM. ViewModelType has rx_action and rx_state to make bind more easily.\n\n```swift\nimport Foundation\nimport RxSwift\nimport RxCocoa\n\nstruct MyState: State {\n    var count: Int = 0\n    var color: UIColor = UIColor.white\n    var error: (Error, Action)? = nil\n}\n\nclass ViewModel: ViewModelType\u003cMyState\u003e {\n    \n    let rx_count =  BehaviorRelay\u003cString\u003e(value: \"0\")\n    let rx_color = BehaviorRelay\u003cUIColor\u003e(value: UIColor.white)\n    \n    override init() {\n        super.init()\n\n        // STORE\n        store.set(\n            initialState: MyState(),\n            middlewares: [\n                printCacheValue,\n                consoleLogMiddleware\n            ],\n            reducers: [\n                countReducer,\n                colorReducer\n            ],\n            postwares: [\n                cachePostware\n            ]\n        )\n    }\n    \n    override func on(newState: MyState) {\n        rx_count.accept(String(newState.count))\n        rx_color.accept(newState.color)\n    }\n    \n    override func on(error: Error, action: Action) {\n        \n    }\n    \n    deinit {\n        print(\"[## deinit ##]\")\n    }\n}\n```\n\n### Make ViewController\n\n```swift\nimport UIKit\nimport RxSwift\nimport RxCocoa\n\nclass ViewController: UIViewController {\n    \n    @IBOutlet weak var countLabel: UILabel!\n    @IBOutlet weak var minusButton: UIButton!\n    @IBOutlet weak var colorButton: UIButton!\n    @IBOutlet weak var plusButton: UIButton!\n    \n    \n    private let viewModel = ViewModel()\n    private let disposeBag = DisposeBag()\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        plusButton.rx.tap.map { IncreaseAction() }.bind(to: viewModel.rx_action).disposed(by: disposeBag)\n        minusButton.rx.tap.map { DecreaseAction() }.bind(to: viewModel.rx_action).disposed(by: disposeBag)\n        colorButton.rx.tap.map { RandomColorAction() }.bind(to: viewModel.rx_action).disposed(by: disposeBag)\n\n        viewModel.rx_color\n            .asDriver()\n            .drive(onNext: { [weak self] (color) in\n                if self?.view.backgroundColor != color {\n                    self?.view.backgroundColor = color\n                }\n            })\n            .disposed(by: disposeBag)\n        \n        viewModel.rx_count\n            .asDriver()\n            .drive(onNext: { [weak self] (countString) in\n                self?.countLabel.text = countString\n            })\n            .disposed(by: disposeBag)\n    }\n\n    override func didReceiveMemoryWarning() {\n        super.didReceiveMemoryWarning()\n    }\n        \n}\n```\n\n## MIT License\n\nThe MIT License\n\nCopyright © 2018 Sungcheol Kim, http://github.com/ReactComponentKit/BKRedux\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactcomponentkit%2Fbkredux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactcomponentkit%2Fbkredux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactcomponentkit%2Fbkredux/lists"}