{"id":18264744,"url":"https://github.com/reactcomponentkit/emojicollection","last_synced_at":"2025-10-10T00:33:49.469Z","repository":{"id":137750979,"uuid":"146163844","full_name":"ReactComponentKit/EmojiCollection","owner":"ReactComponentKit","description":"EmojiCollection is a example for ReactComponentKit","archived":false,"fork":false,"pushed_at":"2019-09-15T06:23:54.000Z","size":6260,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-09T01:41:59.168Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-26T08:24:38.000Z","updated_at":"2019-09-15T06:23:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"acdcf6eb-f8e7-406f-83f9-95fb474364f7","html_url":"https://github.com/ReactComponentKit/EmojiCollection","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ReactComponentKit/EmojiCollection","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FEmojiCollection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FEmojiCollection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FEmojiCollection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FEmojiCollection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ReactComponentKit","download_url":"https://codeload.github.com/ReactComponentKit/EmojiCollection/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactComponentKit%2FEmojiCollection/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002360,"owners_count":26083357,"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","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-11-05T11:15:48.025Z","updated_at":"2025-10-10T00:33:49.451Z","avatar_url":"https://github.com/ReactComponentKit.png","language":"Swift","readme":"# EmojiCollection\n\nThis is [ReactComponentKit](https://github.com/ReactComponentKit/ReactComponentKit) example. EmojiCollection is built on Components, MVVM and Redux.\n\n## Screenshot\n\n![](art/shot.png)\n\n## What is ReactComponentKit\n\nReactComponentKit is a library for building a UIViewController based on Component. Additionary, It architect UIViewController as Redux with MVVM. If you use ReactComponentKit, You can make many scenes(UIViewController) more easily. You can share components among scenes. \n\n## Using Diff algorithm for UICollectionView and UITableview\n\nReactComponentKit provides easy way to update UICollectionView and UITableView. Using diff, you can easily insert, delete or shuffle items like below :)\n\n![](art/video.gif)\n\n## How to getting start?\n\n### Define Actions\n\nWe'll defien three actions for our emoji collection app. AddEmojiAction, RemoveEmojiAction and ShuffleEmojiAction.\n\n#### AddEmojiAction\n\n```swift\nstruct AddEmojiAction: Action {\n    let section: Int\n    let emoji: String\n}\n```\n\n#### RemoveEmojiAction\n\n```swift\nstruct RemoveEmojiAction: Action {\n    let section: Int\n    let index: Int\n}\n```\n\n#### ShuffleEmojiAction\n\n```swift\nstruct ShuffleEmojiAction: Action {   \n}\n```\n\n### Define Reducers\n\nWe need three reducers to mutate our state. There is no when statement and type castring for actions. it is just a pure functions.\n\n#### addEmoji\n\n```swift\nfunc addEmoji(state: EmojiCollectionState, action: AddEmojiAction) -\u003e EmojiCollectionState {\n    return state.copy {\n        $0.emoji[action.section].append(action.emoji)\n    }\n}\n```\n\n#### removeEmoji\n\n```swift\nfunc removeEmoji(state: EmojiCollectionState, action: RemoveEmojiAction) -\u003e EmojiCollectionState {\n    return state.copy {\n        $0.emoji[action.section].remove(at: action.index)\n    }\n}\n```\n\n#### shuffleEmoji\n\n```swift\nfunc shuffleEmoji(state: EmojiCollectionState, action: ShuffleEmojiAction) -\u003e EmojiCollectionState {\n    return state.copy {\n        for (index, var section) in $0.emoji.enumerated() {\n            section.shuffle()\n            $0.emoji[index] = section\n        }\n    }\n}\n```\n\n#### makeCollectionViewSectionModels\n\nIt is needed for our collection view. UICollectionView in ReactComponentKit is built up on the models for items and sections.\n\n```swift\nfunc makeCollectionViewSectionModels(state: EmojiCollectionState) -\u003e EmojiCollectionState {\n    let emojiGroupList = state.emoji\n    let sections = emojiGroupList.enumerated().map { (groupIndex, emojiGroup) -\u003e DefaultSectionModel in\n        \n        let emojiBoxModels = emojiGroup.map({ (emoji) -\u003e EmojiBoxModel in\n            EmojiBoxModel(emoji: emoji)\n        })\n        \n        let section = DefaultSectionModel(items: emojiBoxModels, header: EmojiSectionHeaderModel(title: \"  Emoji Section \\(groupIndex)\"), footer: nil)\n        section.minimumInteritemSpacing = 0\n        section.minimumLineSpacing = 2\n        section.inset = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)\n        return section\n        \n    }\n    \n    return state.copy { $0.sections = sections }\n}\n```\n\n### Define ViewModel and Action Flows\n\nWe need to define ViewModel and in there we should setup store and define action flows.\n\n#### Set up store and define action flows\n\nWe can define action flows in initStore block. We couldn't access the store directly so we should access it with initStore method.\n\n```swift\noverride func setupStore() {\n    initStore { store in\n        store.initial(state: EmojiCollectionState())\n        store.beforeActionFlow(logAction)\n        \n        store.flow(action: AddEmojiAction.self)\n            .flow(\n                addEmoji,\n                { state, _ in makeCollectionViewSectionModels(state: state) }\n            )\n        \n        store.flow(action: RemoveEmojiAction.self)\n            .flow(\n                removeEmoji,\n                { state, _ in makeCollectionViewSectionModels(state: state) }\n            )\n        \n        store.flow(action: ShuffleEmojiAction.self)\n            .flow(\n                shuffleEmoji,\n                { state, _ in makeCollectionViewSectionModels(state: state) }\n            )\n        }\n}\n```\n\n#### Define ViewModel\n\n```swift\nstruct EmojiCollectionState: State {\n    var emoji: [[String]] = [[], [], []]\n    var sections: [DefaultSectionModel] = []\n    var error: RCKError? = nil\n}\n\nclass EmojiCollectionViewModel: RCKViewModel\u003cEmojiCollectionState\u003e {\n    \n    private var emojiGroupList: [[String]]? = nil\n    let sections =  Output\u003c[DefaultSectionModel]\u003e(value: [])\n        \n    override func setupStore() {\n        initStore { store in\n            store.initial(state: EmojiCollectionState())\n            store.beforeActionFlow(logAction)\n            \n            store.flow(action: AddEmojiAction.self)\n                .flow(\n                    addEmoji,\n                    { state, _ in makeCollectionViewSectionModels(state: state) }\n                )\n            \n            store.flow(action: RemoveEmojiAction.self)\n                .flow(\n                    removeEmoji,\n                    { state, _ in makeCollectionViewSectionModels(state: state) }\n                )\n            \n            store.flow(action: ShuffleEmojiAction.self)\n                .flow(\n                    shuffleEmoji,\n                    { state, _ in makeCollectionViewSectionModels(state: state) }\n                )\n            }\n    }\n    \n    override func on(newState: EmojiCollectionState) {\n        emojiGroupList = newState.emoji\n        sections.accept(newState.sections)\n    }\n    \n    func randomIndexToDelete(at section: Int) -\u003e Int? {\n        guard let emojiGroupList = emojiGroupList else { return nil }\n        guard emojiGroupList[section].count \u003e 0 else { return nil }\n        return Int(arc4random()) % emojiGroupList[section].count\n    }\n}\n```\n\n\n## MIT License\n\nThe MIT License\n\nCopyright © 2018 Sungcheol Kim, https://github.com/ReactComponentKit/EmojiCollectionView\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%2Femojicollection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactcomponentkit%2Femojicollection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactcomponentkit%2Femojicollection/lists"}