{"id":21697825,"url":"https://github.com/viniciusdacal/redux-arc","last_synced_at":"2025-04-12T12:21:28.521Z","repository":{"id":72155449,"uuid":"95887492","full_name":"viniciusdacal/redux-arc","owner":"viniciusdacal","description":"A declarative way to make request with redux actions","archived":false,"fork":false,"pushed_at":"2018-12-24T14:04:12.000Z","size":1068,"stargazers_count":160,"open_issues_count":1,"forks_count":10,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-26T07:03:56.858Z","etag":null,"topics":["async","middleware","react","redux","requests"],"latest_commit_sha":null,"homepage":"http://redux-arc.js.org","language":"JavaScript","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/viniciusdacal.png","metadata":{"files":{"readme":"README.html","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":"2017-06-30T12:43:48.000Z","updated_at":"2023-11-12T20:30:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"c95826d7-dd8f-495f-9e37-af563361199d","html_url":"https://github.com/viniciusdacal/redux-arc","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusdacal%2Fredux-arc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusdacal%2Fredux-arc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusdacal%2Fredux-arc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusdacal%2Fredux-arc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/viniciusdacal","download_url":"https://codeload.github.com/viniciusdacal/redux-arc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248565182,"owners_count":21125435,"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":["async","middleware","react","redux","requests"],"created_at":"2024-11-25T19:29:42.728Z","updated_at":"2025-04-12T12:21:28.511Z","avatar_url":"https://github.com/viniciusdacal.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!DOCTYPE html\u003e\u003chtml\u003e\u003chead\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cstyle\u003ebody {\n  max-width: 980px;\n  border: 1px solid #ddd;\n  outline: 1300px solid #fff;\n  margin: 16px auto;\n}\n\nbody .markdown-body\n{\n  padding: 45px;\n}\n\n@font-face {\n  font-family: fontawesome-mini;\n  src: url(data:font/woff;charset=utf-8;base64,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) format('woff');\n}\n\n@font-face {\n  font-family: octicons-anchor;\n  src: url(data:font/woff;charset=utf-8;base64,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) format('woff');\n}\n\n.markdown-body {\n  font-family: sans-serif;\n  -ms-text-size-adjust: 100%;\n  -webkit-text-size-adjust: 100%;\n  color: #333333;\n  overflow: hidden;\n  font-family: \"Helvetica Neue\", Helvetica, \"Segoe UI\", Arial, freesans, sans-serif;\n  font-size: 16px;\n  line-height: 1.6;\n  word-wrap: break-word;\n}\n\n.markdown-body a {\n  background: transparent;\n}\n\n.markdown-body a:active,\n.markdown-body a:hover {\n  outline: 0;\n}\n\n.markdown-body b,\n.markdown-body strong {\n  font-weight: bold;\n}\n\n.markdown-body mark {\n  background: #ff0;\n  color: #000;\n  font-style: italic;\n  font-weight: bold;\n}\n\n.markdown-body sub,\n.markdown-body sup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n.markdown-body sup {\n  top: -0.5em;\n}\n.markdown-body sub {\n  bottom: -0.25em;\n}\n\n.markdown-body h1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n.markdown-body img {\n  border: 0;\n}\n\n.markdown-body hr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n.markdown-body pre {\n  overflow: auto;\n}\n\n.markdown-body code,\n.markdown-body kbd,\n.markdown-body pre,\n.markdown-body samp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\n.markdown-body input {\n  color: inherit;\n  font: inherit;\n  margin: 0;\n}\n\n.markdown-body html input[disabled] {\n  cursor: default;\n}\n\n.markdown-body input {\n  line-height: normal;\n}\n\n.markdown-body input[type=\"checkbox\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\n.markdown-body table {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.markdown-body td,\n.markdown-body th {\n  padding: 0;\n}\n\n.markdown-body .codehilitetable {\n  border: 0;\n  border-spacing: 0;\n}\n\n.markdown-body .codehilitetable tr {\n  border: 0;\n}\n\n.markdown-body .codehilitetable pre,\n.markdown-body .codehilitetable div.codehilite {\n  margin: 0;\n}\n\n.markdown-body .linenos,\n.markdown-body .code,\n.markdown-body .codehilitetable td {\n  border: 0;\n  padding: 0;\n}\n\n.markdown-body td:not(.linenos) .linenodiv {\n  padding: 0 !important;\n}\n\n.markdown-body .code {\n  width: 100%;\n}\n\n.markdown-body .linenos div pre,\n.markdown-body .linenodiv pre,\n.markdown-body .linenodiv {\n  border: 0;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n  -webkit-border-top-left-radius: 3px;\n  -webkit-border-bottom-left-radius: 3px;\n  -moz-border-radius-topleft: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  border-top-left-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n\n.markdown-body .code div pre,\n.markdown-body .code div {\n  border: 0;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n  -webkit-border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n\n.markdown-body * {\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n.markdown-body input {\n  font: 13px Helvetica, arial, freesans, clean, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  line-height: 1.4;\n}\n\n.markdown-body a {\n  color: #4183c4;\n  text-decoration: none;\n}\n\n.markdown-body a:hover,\n.markdown-body a:focus,\n.markdown-body a:active {\n  text-decoration: underline;\n}\n\n.markdown-body hr {\n  height: 0;\n  margin: 15px 0;\n  overflow: hidden;\n  background: transparent;\n  border: 0;\n  border-bottom: 1px solid #ddd;\n}\n\n.markdown-body hr:before,\n.markdown-body hr:after {\n  display: table;\n  content: \" \";\n}\n\n.markdown-body hr:after {\n  clear: both;\n}\n\n.markdown-body h1,\n.markdown-body h2,\n.markdown-body h3,\n.markdown-body h4,\n.markdown-body h5,\n.markdown-body h6 {\n  margin-top: 15px;\n  margin-bottom: 15px;\n  line-height: 1.1;\n}\n\n.markdown-body h1 {\n  font-size: 30px;\n}\n\n.markdown-body h2 {\n  font-size: 21px;\n}\n\n.markdown-body h3 {\n  font-size: 16px;\n}\n\n.markdown-body h4 {\n  font-size: 14px;\n}\n\n.markdown-body h5 {\n  font-size: 12px;\n}\n\n.markdown-body h6 {\n  font-size: 11px;\n}\n\n.markdown-body blockquote {\n  margin: 0;\n}\n\n.markdown-body ul,\n.markdown-body ol {\n  padding: 0;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.markdown-body ol ol,\n.markdown-body ul ol {\n  list-style-type: lower-roman;\n}\n\n.markdown-body ul ul ol,\n.markdown-body ul ol ol,\n.markdown-body ol ul ol,\n.markdown-body ol ol ol {\n  list-style-type: lower-alpha;\n}\n\n.markdown-body dd {\n  margin-left: 0;\n}\n\n.markdown-body code,\n.markdown-body pre,\n.markdown-body samp {\n  font-family: Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n  font-size: 12px;\n}\n\n.markdown-body pre {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.markdown-body kbd {\n  background-color: #e7e7e7;\n  background-image: -moz-linear-gradient(#fefefe, #e7e7e7);\n  background-image: -webkit-linear-gradient(#fefefe, #e7e7e7);\n  background-image: linear-gradient(#fefefe, #e7e7e7);\n  background-repeat: repeat-x;\n  border-radius: 2px;\n  border: 1px solid #cfcfcf;\n  color: #000;\n  padding: 3px 5px;\n  line-height: 10px;\n  font: 11px Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n  display: inline-block;\n}\n\n.markdown-body\u003e*:first-child {\n  margin-top: 0 !important;\n}\n\n.markdown-body\u003e*:last-child {\n  margin-bottom: 0 !important;\n}\n\n.markdown-body .headeranchor-link {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  display: block;\n  padding-right: 6px;\n  padding-left: 30px;\n  margin-left: -30px;\n}\n\n.markdown-body .headeranchor-link:focus {\n  outline: none;\n}\n\n.markdown-body h1,\n.markdown-body h2,\n.markdown-body h3,\n.markdown-body h4,\n.markdown-body h5,\n.markdown-body h6 {\n  position: relative;\n  margin-top: 1em;\n  margin-bottom: 16px;\n  font-weight: bold;\n  line-height: 1.4;\n}\n\n.markdown-body h1 .headeranchor,\n.markdown-body h2 .headeranchor,\n.markdown-body h3 .headeranchor,\n.markdown-body h4 .headeranchor,\n.markdown-body h5 .headeranchor,\n.markdown-body h6 .headeranchor {\n  display: none;\n  color: #000;\n  vertical-align: middle;\n}\n\n.markdown-body h1:hover .headeranchor-link,\n.markdown-body h2:hover .headeranchor-link,\n.markdown-body h3:hover .headeranchor-link,\n.markdown-body h4:hover .headeranchor-link,\n.markdown-body h5:hover .headeranchor-link,\n.markdown-body h6:hover .headeranchor-link {\n  height: 1em;\n  padding-left: 8px;\n  margin-left: -30px;\n  line-height: 1;\n  text-decoration: none;\n}\n\n.markdown-body h1:hover .headeranchor-link .headeranchor,\n.markdown-body h2:hover .headeranchor-link .headeranchor,\n.markdown-body h3:hover .headeranchor-link .headeranchor,\n.markdown-body h4:hover .headeranchor-link .headeranchor,\n.markdown-body h5:hover .headeranchor-link .headeranchor,\n.markdown-body h6:hover .headeranchor-link .headeranchor {\n  display: inline-block;\n}\n\n.markdown-body h1 {\n  padding-bottom: 0.3em;\n  font-size: 2.25em;\n  line-height: 1.2;\n  border-bottom: 1px solid #eee;\n}\n\n.markdown-body h2 {\n  padding-bottom: 0.3em;\n  font-size: 1.75em;\n  line-height: 1.225;\n  border-bottom: 1px solid #eee;\n}\n\n.markdown-body h3 {\n  font-size: 1.5em;\n  line-height: 1.43;\n}\n\n.markdown-body h4 {\n  font-size: 1.25em;\n}\n\n.markdown-body h5 {\n  font-size: 1em;\n}\n\n.markdown-body h6 {\n  font-size: 1em;\n  color: #777;\n}\n\n.markdown-body p,\n.markdown-body blockquote,\n.markdown-body ul,\n.markdown-body ol,\n.markdown-body dl,\n.markdown-body table,\n.markdown-body pre,\n.markdown-body .admonition {\n  margin-top: 0;\n  margin-bottom: 16px;\n}\n\n.markdown-body hr {\n  height: 4px;\n  padding: 0;\n  margin: 16px 0;\n  background-color: #e7e7e7;\n  border: 0 none;\n}\n\n.markdown-body ul,\n.markdown-body ol {\n  padding-left: 2em;\n}\n\n.markdown-body ul ul,\n.markdown-body ul ol,\n.markdown-body ol ol,\n.markdown-body ol ul {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.markdown-body li\u003ep {\n  margin-top: 16px;\n}\n\n.markdown-body dl {\n  padding: 0;\n}\n\n.markdown-body dl dt {\n  padding: 0;\n  margin-top: 16px;\n  font-size: 1em;\n  font-style: italic;\n  font-weight: bold;\n}\n\n.markdown-body dl dd {\n  padding: 0 16px;\n  margin-bottom: 16px;\n}\n\n.markdown-body blockquote {\n  padding: 0 15px;\n  color: #777;\n  border-left: 4px solid #ddd;\n}\n\n.markdown-body blockquote\u003e:first-child {\n  margin-top: 0;\n}\n\n.markdown-body blockquote\u003e:last-child {\n  margin-bottom: 0;\n}\n\n.markdown-body table {\n  display: block;\n  width: 100%;\n  overflow: auto;\n  word-break: normal;\n  word-break: keep-all;\n}\n\n.markdown-body table th {\n  font-weight: bold;\n}\n\n.markdown-body table th,\n.markdown-body table td {\n  padding: 6px 13px;\n  border: 1px solid #ddd;\n}\n\n.markdown-body table tr {\n  background-color: #fff;\n  border-top: 1px solid #ccc;\n}\n\n.markdown-body table tr:nth-child(2n) {\n  background-color: #f8f8f8;\n}\n\n.markdown-body img {\n  max-width: 100%;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n.markdown-body code,\n.markdown-body samp {\n  padding: 0;\n  padding-top: 0.2em;\n  padding-bottom: 0.2em;\n  margin: 0;\n  font-size: 85%;\n  background-color: rgba(0,0,0,0.04);\n  border-radius: 3px;\n}\n\n.markdown-body code:before,\n.markdown-body code:after {\n  letter-spacing: -0.2em;\n  content: \"\\00a0\";\n}\n\n.markdown-body pre\u003ecode {\n  padding: 0;\n  margin: 0;\n  font-size: 100%;\n  word-break: normal;\n  white-space: pre;\n  background: transparent;\n  border: 0;\n}\n\n.markdown-body .codehilite {\n  margin-bottom: 16px;\n}\n\n.markdown-body .codehilite pre,\n.markdown-body pre {\n  padding: 16px;\n  overflow: auto;\n  font-size: 85%;\n  line-height: 1.45;\n  background-color: #f7f7f7;\n  border-radius: 3px;\n}\n\n.markdown-body .codehilite pre {\n  margin-bottom: 0;\n  word-break: normal;\n}\n\n.markdown-body pre {\n  word-wrap: normal;\n}\n\n.markdown-body pre code {\n  display: inline;\n  max-width: initial;\n  padding: 0;\n  margin: 0;\n  overflow: initial;\n  line-height: inherit;\n  word-wrap: normal;\n  background-color: transparent;\n  border: 0;\n}\n\n.markdown-body pre code:before,\n.markdown-body pre code:after {\n  content: normal;\n}\n\n/* Admonition */\n.markdown-body .admonition {\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  position: relative;\n  border-radius: 3px;\n  border: 1px solid #e0e0e0;\n  border-left: 6px solid #333;\n  padding: 10px 10px 10px 30px;\n}\n\n.markdown-body .admonition table {\n  color: #333;\n}\n\n.markdown-body .admonition p {\n  padding: 0;\n}\n\n.markdown-body .admonition-title {\n  font-weight: bold;\n  margin: 0;\n}\n\n.markdown-body .admonition\u003e.admonition-title {\n  color: #333;\n}\n\n.markdown-body .attention\u003e.admonition-title {\n  color: #a6d796;\n}\n\n.markdown-body .caution\u003e.admonition-title {\n  color: #d7a796;\n}\n\n.markdown-body .hint\u003e.admonition-title {\n  color: #96c6d7;\n}\n\n.markdown-body .danger\u003e.admonition-title {\n  color: #c25f77;\n}\n\n.markdown-body .question\u003e.admonition-title {\n  color: #96a6d7;\n}\n\n.markdown-body .note\u003e.admonition-title {\n  color: #d7c896;\n}\n\n.markdown-body .admonition:before,\n.markdown-body .attention:before,\n.markdown-body .caution:before,\n.markdown-body .hint:before,\n.markdown-body .danger:before,\n.markdown-body .question:before,\n.markdown-body .note:before {\n  font: normal normal 16px fontawesome-mini;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  line-height: 1.5;\n  color: #333;\n  position: absolute;\n  left: 0;\n  top: 0;\n  padding-top: 10px;\n  padding-left: 10px;\n}\n\n.markdown-body .admonition:before {\n  content: \"\\f056\\00a0\";\n  color: 333;\n}\n\n.markdown-body .attention:before {\n  content: \"\\f058\\00a0\";\n  color: #a6d796;\n}\n\n.markdown-body .caution:before {\n  content: \"\\f06a\\00a0\";\n  color: #d7a796;\n}\n\n.markdown-body .hint:before {\n  content: \"\\f05a\\00a0\";\n  color: #96c6d7;\n}\n\n.markdown-body .danger:before {\n  content: \"\\f057\\00a0\";\n  color: #c25f77;\n}\n\n.markdown-body .question:before {\n  content: \"\\f059\\00a0\";\n  color: #96a6d7;\n}\n\n.markdown-body .note:before {\n  content: \"\\f040\\00a0\";\n  color: #d7c896;\n}\n\n.markdown-body .admonition::after {\n  content: normal;\n}\n\n.markdown-body .attention {\n  border-left: 6px solid #a6d796;\n}\n\n.markdown-body .caution {\n  border-left: 6px solid #d7a796;\n}\n\n.markdown-body .hint {\n  border-left: 6px solid #96c6d7;\n}\n\n.markdown-body .danger {\n  border-left: 6px solid #c25f77;\n}\n\n.markdown-body .question {\n  border-left: 6px solid #96a6d7;\n}\n\n.markdown-body .note {\n  border-left: 6px solid #d7c896;\n}\n\n.markdown-body .admonition\u003e*:first-child {\n  margin-top: 0 !important;\n}\n\n.markdown-body .admonition\u003e*:last-child {\n  margin-bottom: 0 !important;\n}\n\n/* progress bar*/\n.markdown-body .progress {\n  display: block;\n  width: 300px;\n  margin: 10px 0;\n  height: 24px;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n  background-color: #ededed;\n  position: relative;\n  box-shadow: inset -1px 1px 3px rgba(0, 0, 0, .1);\n}\n\n.markdown-body .progress-label {\n  position: absolute;\n  text-align: center;\n  font-weight: bold;\n  width: 100%; margin: 0;\n  line-height: 24px;\n  color: #333;\n  text-shadow: 1px 1px 0 #fefefe, -1px -1px 0 #fefefe, -1px 1px 0 #fefefe, 1px -1px 0 #fefefe, 0 1px 0 #fefefe, 0 -1px 0 #fefefe, 1px 0 0 #fefefe, -1px 0 0 #fefefe, 1px 1px 2px #000;\n  -webkit-font-smoothing: antialiased !important;\n  white-space: nowrap;\n  overflow: hidden;\n}\n\n.markdown-body .progress-bar {\n  height: 24px;\n  float: left;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n  background-color: #96c6d7;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(0, 0, 0, .1);\n  background-size: 30px 30px;\n  background-image: -webkit-linear-gradient(\n    135deg, rgba(255, 255, 255, .4) 27%,\n    transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%,\n    transparent 77%, transparent\n  );\n  background-image: -moz-linear-gradient(\n    135deg,\n    rgba(255, 255, 255, .4) 27%, transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%, transparent 77%,\n    transparent\n  );\n  background-image: -ms-linear-gradient(\n    135deg,\n    rgba(255, 255, 255, .4) 27%, transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%, transparent 77%,\n    transparent\n  );\n  background-image: -o-linear-gradient(\n    135deg,\n    rgba(255, 255, 255, .4) 27%, transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%, transparent 77%,\n    transparent\n  );\n  background-image: linear-gradient(\n    135deg,\n    rgba(255, 255, 255, .4) 27%, transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%, transparent 77%,\n    transparent\n  );\n}\n\n.markdown-body .progress-100plus .progress-bar {\n  background-color: #a6d796;\n}\n\n.markdown-body .progress-80plus .progress-bar {\n  background-color: #c6d796;\n}\n\n.markdown-body .progress-60plus .progress-bar {\n  background-color: #d7c896;\n}\n\n.markdown-body .progress-40plus .progress-bar {\n  background-color: #d7a796;\n}\n\n.markdown-body .progress-20plus .progress-bar {\n  background-color: #d796a6;\n}\n\n.markdown-body .progress-0plus .progress-bar {\n  background-color: #c25f77;\n}\n\n.markdown-body .candystripe-animate .progress-bar{\n  -webkit-animation: animate-stripes 3s linear infinite;\n  -moz-animation: animate-stripes 3s linear infinite;\n  animation: animate-stripes 3s linear infinite;\n}\n\n@-webkit-keyframes animate-stripes {\n  0% {\n    background-position: 0 0;\n  }\n\n  100% {\n    background-position: 60px 0;\n  }\n}\n\n@-moz-keyframes animate-stripes {\n  0% {\n    background-position: 0 0;\n  }\n\n  100% {\n    background-position: 60px 0;\n  }\n}\n\n@keyframes animate-stripes {\n  0% {\n    background-position: 0 0;\n  }\n\n  100% {\n    background-position: 60px 0;\n  }\n}\n\n.markdown-body .gloss .progress-bar {\n  box-shadow:\n    inset 0 4px 12px rgba(255, 255, 255, .7),\n    inset 0 -12px 0 rgba(0, 0, 0, .05);\n}\n\n/* Multimarkdown Critic Blocks */\n.markdown-body .critic_mark {\n  background: #ff0;\n}\n\n.markdown-body .critic_delete {\n  color: #c82829;\n  text-decoration: line-through;\n}\n\n.markdown-body .critic_insert {\n  color: #718c00 ;\n  text-decoration: underline;\n}\n\n.markdown-body .critic_comment {\n  color: #8e908c;\n  font-style: italic;\n}\n\n.markdown-body .headeranchor {\n  font: normal normal 16px octicons-anchor;\n  line-height: 1;\n  display: inline-block;\n  text-decoration: none;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.headeranchor:before {\n  content: '\\f05c';\n}\n\n.markdown-body .task-list-item {\n  list-style-type: none;\n}\n\n.markdown-body .task-list-item+.task-list-item {\n  margin-top: 3px;\n}\n\n.markdown-body .task-list-item input {\n  margin: 0 4px 0.25em -20px;\n  vertical-align: middle;\n}\n\n/* Media */\n@media only screen and (min-width: 480px) {\n  .markdown-body {\n    font-size:14px;\n  }\n}\n\n@media only screen and (min-width: 768px) {\n  .markdown-body {\n    font-size:16px;\n  }\n}\n\n@media print {\n  .markdown-body * {\n    background: transparent !important;\n    color: black !important;\n    filter:none !important;\n    -ms-filter: none !important;\n  }\n\n  .markdown-body {\n    font-size:12pt;\n    max-width:100%;\n    outline:none;\n    border: 0;\n  }\n\n  .markdown-body a,\n  .markdown-body a:visited {\n    text-decoration: underline;\n  }\n\n  .markdown-body .headeranchor-link {\n    display: none;\n  }\n\n  .markdown-body a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  .markdown-body abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  .markdown-body .ir a:after,\n  .markdown-body a[href^=\"javascript:\"]:after,\n  .markdown-body a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  .markdown-body pre {\n    white-space: pre;\n    white-space: pre-wrap;\n    word-wrap: break-word;\n  }\n\n  .markdown-body pre,\n  .markdown-body blockquote {\n    border: 1px solid #999;\n    padding-right: 1em;\n    page-break-inside: avoid;\n  }\n\n  .markdown-body .progress,\n  .markdown-body .progress-bar {\n    -moz-box-shadow: none;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n  }\n\n  .markdown-body .progress {\n    border: 1px solid #ddd;\n  }\n\n  .markdown-body .progress-bar {\n    height: 22px;\n    border-right: 1px solid #ddd;\n  }\n\n  .markdown-body tr,\n  .markdown-body img {\n    page-break-inside: avoid;\n  }\n\n  .markdown-body img {\n    max-width: 100% !important;\n  }\n\n  .markdown-body p,\n  .markdown-body h2,\n  .markdown-body h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  .markdown-body h2,\n  .markdown-body h3 {\n    page-break-after: avoid;\n  }\n}\n\u003c/style\u003e\u003ctitle\u003eREADME\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003carticle class=\"markdown-body\"\u003e\u003cp\u003e\u003cimg src=\"https://github.com/viniciusdacal/redux-arc/blob/master/arc-64.png?raw=true\" height=\"64\" /\u003e\u003c/p\u003e\n\u003cp\u003eCreate scalable, no-boilerplate redux Apps!\u003c/p\u003e\n\u003cp\u003eArc is an abstraction layer to help you reduce boilerplate on redux-apps and also, organize better your code. Additionally, it has utilities to handle async requests.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://travis-ci.org/viniciusdacal/redux-arc\"\u003e\u003cimg alt=\"build status\" src=\"https://img.shields.io/travis/viniciusdacal/redux-arc/master.svg?style=flat-square\" /\u003e\u003c/a\u003e \u003ca href=\"https://www.npmjs.com/package/redux-arc\"\u003e\u003cimg alt=\"npm version\" src=\"https://img.shields.io/npm/v/redux-arc.svg?style=flat-square\" /\u003e\u003c/a\u003e\u003cbr /\u003e\n\u003ca href=\"https://coveralls.io/github/viniciusdacal/redux-arc?branch=master\"\u003e\u003cimg alt=\"Coverage Status\" src=\"https://coveralls.io/repos/github/viniciusdacal/redux-arc/badge.svg?branch=master\" /\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"why\"\u003e\u003ca name=\"user-content-why\" href=\"#why\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eWhy\u003c/h2\u003e\n\u003cp\u003eRedux is awesome! But people often complain about how much boilerplate they have to write when using it. Part of this problem, is because they feel unproductive defining constants, action creators and big reducers, but also because they don\u0026rsquo;t have a clear idea on how to organize their project, or even how to proper handle async requests. This project, intends to help on all that aspects!\u003c/p\u003e\n\u003cp\u003eWe don\u0026rsquo;t intend to recreate the wheel, instead, we tried to use what the community are used with, and build up some approaches together in order to clarify the things about the project architecture, code splitting and the things around actions.\u003c/p\u003e\n\u003ch2 id=\"creators-and-types-are-generated-by-a-config\"\u003e\u003ca name=\"user-content-creators-and-types-are-generated-by-a-config\" href=\"#creators-and-types-are-generated-by-a-config\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eCreators and types are generated by a config\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  // actions.js\n  import { createActions } from 'redux-arc';\n\n  export { types, creators } = createActions('jedi', {\n    add: null,\n  });\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003ch2 id=\"create-reducers-using-createreducers-and-types\"\u003e\u003ca name=\"user-content-create-reducers-using-createreducers-and-types\" href=\"#create-reducers-using-createreducers-and-types\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eCreate reducers using createReducers and types:\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  import { createReducers } from 'redux-arc';\n  import { types } from './actions';\n\n  const INITIAL_STATE = [];\n  const HANDLERS = {\n    [types.ADD]: (state, action) =\u0026gt; [...state, action.payload]\n  };\n\n  export default createReducers(INITIAL_STATE, HANDLERS);\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003ch2 id=\"call-the-creators-providing-payload-and-meta\"\u003e\u003ca name=\"user-content-call-the-creators-providing-payload-and-meta\" href=\"#call-the-creators-providing-payload-and-meta\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eCall the creators providing payload and meta\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  import { creators } from './actions';\n\n  const payload = {\n    name: 'Luke',\n    master: 'Yoda',\n  };\n  const meta = { foo: 'bar' };\n\n  dispatch(creators.add(payload, meta))\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003ch2 id=\"create-async-actions\"\u003e\u003ca name=\"user-content-create-async-actions\" href=\"#create-async-actions\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eCreate Async Actions\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  import { createActions } from 'redux-arc';\n\n  export { types, creators } = createActions('jedi', {\n    add: { url: '/api/jedi' method: 'post'},\n  });\n\n  dispatch(creators.add(payload, meta));\n\n  types.ADD.REQUEST // JEDI_ADD_REQUEST\n  types.ADD.RESPONSE // JEDI_ADD_RESPONSE\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cblockquote\u003e\n\u003cp\u003ecreateActions creates both, regular and async actions. Async types has REQUEST and RESPONSE type, respectively to when a request starts and when it finishes.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch1 id=\"getting-started\"\u003e\u003ca name=\"user-content-getting-started\" href=\"#getting-started\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eGetting started\u003c/h1\u003e\n\u003cp\u003e\u003cpre\u003e\u003ccode class=\"bash\"\u003eyarn add redux-arc\n\u003c/code\u003e\u003c/pre\u003e\u003cbr /\u003e\nor\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"bash\"\u003enpm i --save redux-arc\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eTo understand this docs, you should have a good understand of redux: what are Action creators, what are reducers, middlewares and also, what is a Flux Standard Action. So please, if you need a recap on those concepts, read the links bellow:\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://redux.js.org/\"\u003eRedux Docs\u003c/a\u003e\u003cbr /\u003e\n\u003ca href=\"https://github.com/acdlite/flux-standard-action\"\u003eFlux Standard Action\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"action-creators-and-types\"\u003e\u003ca name=\"user-content-action-creators-and-types\" href=\"#action-creators-and-types\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eAction creators and Types\u003c/h1\u003e\n\u003cp\u003eWhen you have to create a new action on redux, the first 2 steps you usually do is defining a \u003cstrong\u003econst\u003c/strong\u003e to you \u003cem\u003eaction type\u003c/em\u003e and then defining an \u003cem\u003eaction creator\u003c/em\u003e.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003econst NEW_JEDI = 'NEW_JEDI';\n\nconst newJedi = (payload) =\u0026gt; ({\n  type: NEW_JEDI,\n  payload,\n});\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eThe above code is fine, but the problem is, you have dozens or hundreds of action in an application, and you are always writing the same code. Also, if you are not strict on code review, you end up having situations where your action type has a name different from your action creator:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003econst NEW_JEDI = 'NEW_JEDI';\n\nconst addJedi = (payload) =\u0026gt; ({\n  type: NEW_JEDI,\n  payload,\n});\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eThinking in the above issues, Arc has a \u003ccode\u003ecreateAction\u003c/code\u003e function, that you use to define your actions and it generates the types and action creators automatically for you. Take a look:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  import { createActions } from 'redux-arc';\n\n  const { types, creators } = createActions('yourNamespace', {\n    newJedi: null,\n  });\n\n  types.newJedi // YOUR_NAMESPACE_NEW_JEDI\n\n  const payload = {\n    master: 'Yoda',\n    name: 'Luke',\n  };\n\n  creators.newJedi(payload);\n  /*\n  {\n    type: 'YOUR_NAMESPACE_NEW_JEDI',\n    payload: {\n      master: 'Yoda',\n      name: 'Luke',\n    }\n  }\n  */\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eThe \u003ccode\u003ecreateActions\u003c/code\u003e method, expects a namespace as its first argument, this will be uppercased and will serve as a prefix for the actions. As the second parameter, we need to provide a config object, which the key is the action name and the value is an object with default values for \u003cstrong\u003epayload\u003c/strong\u003e and \u003cstrong\u003emeta\u003c/strong\u003e, or \u003ccode\u003enull\u003c/code\u003e if you don\u0026rsquo;t want to provide defaults. Then, it will return \u003cstrong\u003ecreators\u003c/strong\u003e and \u003cstrong\u003etypes\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eBoth creators and types are objects, the first one contains the action creators for the actions you defined. As in the case above we defined an action newJedi, then we have a creator at \u003ccode\u003ecreators.newJedi\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eCreators accepts until three arguments:\u003cbr /\u003e\n - payload: could be of any type. Will become the \u003ccode\u003eaction.payload\u003c/code\u003e\u003cbr /\u003e\n - meta: could be of any type. Will become the \u003ccode\u003eaction.meta\u003c/code\u003e\u003cbr /\u003e\n - error: boolean. Indicates if the action has an error or not. You can omit it if the action has no error.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe api was designed following the flux-standard-action concepts. It can be strict about how your action should look like, but this will help you creating better actions. Also, now you can be sure that the first parameter you provide to the action creator, will become the action.payload.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe types is an object that contains strings. Its keys are the action names, but different from the creators, here they are uppercased:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  types.NEW_JEDI\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eAlso, when you do a console.log to see its content, you can see that we prefix the actions with the namespace you provided:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  const { types } = createActions('yourNamespace', {\n    newJedi: null,\n  });\n\n  types.NEW_JEDI // -\u0026gt; YOUR_NAMESPACE_NEW_JEDI\n\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cblockquote\u003e\n\u003cp\u003eWe decided to have the namespace, to not stop you from having actions with the same name in different modules. Don\u0026rsquo;t worry, you will be able to differ them easily when using redux-dev-tools, just remember to provide unique namespaces.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch1 id=\"async-actions\"\u003e\u003ca name=\"user-content-async-actions\" href=\"#async-actions\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eAsync Actions\u003c/h1\u003e\n\u003cp\u003eOriginally, Arc was created to be an abstraction layer to handle async request in Redux. So, it has all you need about that. The api to generate async actions and types is the same, you only need to provide some additional params in the action config object. Take a look below:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  import { createApiActions } from 'redux-arc';\n\n  const { creators, types } = createActions('todo', {\n    list:   { url: 'api/todo',     method: 'get'  },\n    read:   { url: 'api/todo/:id', method: 'get'  },\n    create: { url: 'api/todo',     method: 'post' },\n    update: { url: 'api/todo/:id', method: 'put'  },\n  });\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eAbove are defined three actions: \u003ccode\u003elist\u003c/code\u003e, \u003ccode\u003eread\u003c/code\u003e, \u003ccode\u003ecreate\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eTwo params are required for a async action config, \u003ccode\u003eurl\u003c/code\u003e and \u003ccode\u003emethod\u003c/code\u003e.\u003cbr /\u003e\n - \u003cstrong\u003eurl\u003c/strong\u003e: You can define any url you want and it also accepts dynamic params, as you can see in the \u003ccode\u003eread\u003c/code\u003e action. We defined a dynamic param \u003cstrong\u003eid\u003c/strong\u003e, inserting \u003ccode\u003e:id\u003c/code\u003e\u003cbr /\u003e\n - \u003cstrong\u003emethod\u003c/strong\u003e: Generally speaking, any http method your request lib supports. This will be used only by you in the asyncMiddleware that you will configure.\u003c/p\u003e\n\u003ch3 id=\"async-creators-and-async-types\"\u003e\u003ca name=\"user-content-async-creators-and-async-types\" href=\"#async-creators-and-async-types\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eAsync Creators and Async Types\u003c/h3\u003e\n\u003cp\u003eAn async creator is very similar to a simple creator. It accepts \u003cstrong\u003epayload\u003c/strong\u003e and \u003cstrong\u003emeta\u003c/strong\u003e as arguments. They will further become the \u003ccode\u003eaction.payload\u003c/code\u003e and \u003ccode\u003eaction.meta\u003c/code\u003e, as in a regular creator. The difference here, is that the meta, should be an object, and its values will be used to parse dynamic urls. Considering that, the creator \u003cstrong\u003eread\u003c/strong\u003e should be used like that:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  const payload = null;\n  const meta = { id: '123' };\n  creators.read(payload, meta);\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eWith the above code, the final url to your read request, would be \u003ccode\u003eapi/todo/123\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eThe async types differ a little bit from the regular ones as well. First, as a api call has two moments (request and response), we need two different types to use inside our reducers. Considering that, Arc returns an object for each type, containing a \u003ccode\u003eREQUEST\u003c/code\u003e and a \u003ccode\u003eRESPONSE\u003c/code\u003e key with the respective types:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  types.READ.REQUEST == 'TODO_READ_REQUEST';\n  types.READ.RESPONSE == 'TODO_READ_RESPONSE';\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003ch3 id=\"async-middleware\"\u003e\u003ca name=\"user-content-async-middleware\" href=\"#async-middleware\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eAsync Middleware\u003c/h3\u003e\n\u003cp\u003eArc doesn\u0026rsquo;t intend to be a request lib, so, you need to tell it how you want to make your requests, and you do that by configuring the asyncMiddleware.\u003c/p\u003e\n\u003cp\u003eIt\u0026rsquo;s quite simple, take a look below in an example using axios:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003eimport { createAsyncMiddleware } from 'redux-arc';\nimport axios from 'axios';\n\nconst asyncTask = store =\u0026gt; done =\u0026gt; (options) =\u0026gt; {\n  const { method, url, payload } = options;\n  const params = method === 'get' ? { params: payload } : payload;\n\n  axios[method](url, params).then((error, response) =\u0026gt; done(error, response));\n};\n\n// create the async middleware\nconst asyncMiddleware = createAsyncMiddleware(asyncTask);\n\n// set it to the Store\nconst store = createStore(\n  reducer,\n  applyMiddleware(asyncMiddleware),\n);\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cblockquote\u003e\n\u003cp\u003eIn the above example, we are using axios, but you can use whatever you want to perform the request, just make sure you call done, passing error and response when the request ends.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eFor more info about \u003cstrong\u003easyncTask\u003c/strong\u003e and \u003cstrong\u003ecreateAsyncMiddleware\u003c/strong\u003e, read \u003ca href=\"http://redux-arc.js.org/docs/basics/ConnectingArcIntoRedux.html\"\u003eConnecting Arc Into Redux\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"reducers\"\u003e\u003ca name=\"user-content-reducers\" href=\"#reducers\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eReducers\u003c/h1\u003e\n\u003cp\u003eBeyond types and action creators, we also have reducers. There are a few ways to deal with them, some approaches use \u003ccode\u003eswitch case\u003c/code\u003e, some others use multiple \u003ccode\u003eIFs\u003c/code\u003e. With most of them, you end up having a lot of code inside the same function, which makes maintenance and focusing hard. I know some approaches mention that you can split your code into small functions when it gets bigger, but why do not start from something that is easy to scale and also allow you to focus on each action separately?\u003c/p\u003e\n\u003cp\u003eThinking about that, we created the function \u003ccode\u003ecreateReducers\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003ecreateReducers\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis factory was created to work standalone, it doesn\u0026rsquo;t require you to use any other feature from Arc. If you like, you can continue creating your actions and types as you always did. Take a look at the example below:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  // vanillaActions.js\n  export const ADD_NEW_JEDI = 'ADD_NEW_JEDI';\n\n  export const addNewJedi = (name, master) =\u0026gt; ({\n    type: ADD_NEW_JEDI,\n    name,\n    master,\n  });\n\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eAbove we defined our types and action creator using pure JavaScript . Below, you can see how we could use it with \u003cstrong\u003ecreateReducers\u003c/strong\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  import { createReducers } from 'redux-arc';\n  import { ADD_NEW_JEDI } from './vanillaActions';\n\n  const INITIAL_STATE = [];\n\n  const onAddNewJedi = (state, action) =\u0026gt; [\n    ...state,\n    { name: action.name, master: action.master },\n  ];\n\n  const HANDLERS = {\n    [ADD_NEW_JEDI]: onAddNewJedi\n  };\n\n  export default createReducers(INITIAL_STATE, HANDLERS);\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eYou must provide a INITIAL_STATE and a HANDLERS object, which the keys should be the action types and the values should be reducers.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUsing createActions with arc\u0026rsquo;s types object\u003c/strong\u003e\u003cbr /\u003e\nAs the types object is a simple JavaScript object, with strings, it fits perfectly with \u003cstrong\u003ecreateReducers\u003c/strong\u003e. Take a look below in an example using both, a regular and a async action with \u003cstrong\u003ecreateReducers\u003c/strong\u003e:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eactions.js\u003c/strong\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e  const { creators, types } = createActions('todo', {\n    list: { url: 'api/todo', method: 'get'  }, // async action\n    reset: null, // regular action,\n  });\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003e\u003cstrong\u003ereducers.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003eimport { createReducers } from 'redux-arc'\nimport { types } from './actions';\n\nconst INITIAL_STATE = {\n  listResult: [],\n  listIsLoading: false,\n  listError: null,\n};\n\nconst onListRequest = (state, action) =\u0026gt; ({\n  ...state,\n  listIsLoading: true,\n  listError: INITIAL_STATE.listError,\n});\n\nconst onListResponse = (state, action) =\u0026gt; {\n  if (action.error) {\n    return {\n      ...state,\n      listIsLoading: INITIAL_STATE.listIsLoading,\n      listError: action.payload,\n    }\n  }\n\n  return {\n    ...state,\n    listIsLoading: INITIAL_STATE.listIsLoading,\n    listResult: action.payload\n  }\n};\n\nconst onReset = state =\u0026gt; INITIAL_STATE;\n\nconst HANDLERS = {\n  [types.LIST.REQUEST]: onListRequest,\n  [types.LIST.RESPONSE]: onListResponse,\n  [types.RESET]: onReset,\n};\n\nexport default createReducers(INITIAL_STATE, HANDLERS);\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eAs we mentioned, we are using two kinds of action types, regular and async.\u003c/p\u003e\n\u003cp\u003eFor the regular, there\u0026rsquo;s no much secret, \u003ccode\u003etypes.RESET\u003c/code\u003e contains a string \u003ccode\u003eTODO_RESET\u003c/code\u003e generated by \u003ccode\u003ecreateActions\u003c/code\u003e, using the namespace and the action name we defined earlier.\u003c/p\u003e\n\u003cp\u003eThe async action, contains an object, with \u003cstrong\u003eREQUEST\u003c/strong\u003e and \u003cstrong\u003eRESPONSE\u003c/strong\u003e keys, each one containing a string, which is the actual type.\u003c/p\u003e\n\u003cp\u003eArc will dispatch the respective request and response action using the same types we have in \u003ccode\u003etypes\u003c/code\u003e object and the same applies for regular actions, so Arc doesn\u0026rsquo;t open breaches for you to commit a typo.\u003c/p\u003e\n\u003ch1 id=\"async-actions_1\"\u003e\u003ca name=\"user-content-async-actions_1\" href=\"#async-actions_1\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eAsync Actions\u003c/h1\u003e\n\u003ch3 id=\"response-action\"\u003e\u003ca name=\"user-content-response-action\" href=\"#response-action\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eResponse action:\u003c/h3\u003e\n\u003cp\u003eWhen the request is done, an action with the response will be dispatched. Considering the list example, the response action would look like this:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e{\n  type: 'JEDI_LIST_RESPONSE', // types.LIST.RESPONSE,\n  meta: {\n    url: 'api/todo',\n    method: 'get',\n  },\n  payload: [\n    // resource list\n  ],\n}\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003ch3 id=\"error-handling\"\u003e\u003ca name=\"user-content-error-handling\" href=\"#error-handling\" class=\"headeranchor-link\" aria-hidden=\"true\"\u003e\u003cspan class=\"headeranchor\"\u003e\u003c/span\u003e\u003c/a\u003eError handling\u003c/h3\u003e\n\u003cp\u003eThe above example is a a response with success. Accordingly to \u003cstrong\u003eFSA\u003c/strong\u003e, errors should be treated as a \u003ca href=\"https://github.com/redux-utilities/flux-standard-action#errors-as-a-first-class-concept\"\u003e\u003cstrong\u003eFirst class concept\u003c/strong\u003e\u003c/a\u003e. In that case, when you got some error in an async request, the response action will come with the error property as \u003ccode\u003etrue\u003c/code\u003e and the payload will be the actual error. Just like the example below:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"js\"\u003e{\n  type: 'JEDI_LIST_RESPONSE', // types.LIST.RESPONSE,\n  meta: {\n    url: 'api/todo',\n    method: 'get',\n  },\n  payload: new Error('the request error'),\n  error: true,\n}\n\u003c/code\u003e\u003c/pre\u003e\u003c/article\u003e\u003c/body\u003e\u003c/html\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviniciusdacal%2Fredux-arc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fviniciusdacal%2Fredux-arc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviniciusdacal%2Fredux-arc/lists"}