{"id":15022233,"url":"https://github.com/pavelivanov/redaction","last_synced_at":"2025-04-12T06:17:49.546Z","repository":{"id":10068484,"uuid":"63901687","full_name":"pavelivanov/redaction","owner":"pavelivanov","description":"Redux reducers without constants and dispatching!","archived":false,"fork":false,"pushed_at":"2023-01-06T17:10:08.000Z","size":739,"stargazers_count":60,"open_issues_count":11,"forks_count":10,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T06:17:31.073Z","etag":null,"topics":["redaction","reducer-creation","reducers"],"latest_commit_sha":null,"homepage":"https://pavelivanov.github.io/redaction/","language":"TypeScript","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/pavelivanov.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","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":"2016-07-21T20:53:12.000Z","updated_at":"2024-07-18T12:00:00.000Z","dependencies_parsed_at":"2023-01-13T15:43:44.061Z","dependency_job_id":null,"html_url":"https://github.com/pavelivanov/redaction","commit_stats":null,"previous_names":["grammka/redbox"],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelivanov%2Fredaction","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelivanov%2Fredaction/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelivanov%2Fredaction/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelivanov%2Fredaction/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pavelivanov","download_url":"https://codeload.github.com/pavelivanov/redaction/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248525141,"owners_count":21118620,"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":["redaction","reducer-creation","reducers"],"created_at":"2024-09-24T19:57:40.614Z","updated_at":"2025-04-12T06:17:49.507Z","avatar_url":"https://github.com/pavelivanov.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp\u003e\n  \u003cimg src=\"./images/redaction-logo-big.png\" height=\"70\" /\u003e\n\u003c/p\u003e\n\n### Redux reducers without constants and dispatching!\n\nRedaction is wrapper for reducers. The main purpose is to refuse from using constants and dispatch method in code.\n\n[![Npm Version](https://badge.fury.io/js/redaction.svg)](https://www.npmjs.com/package/redaction)\n[![Month Downloads](https://img.shields.io/npm/dm/redaction.svg)](http://npm-stat.com/charts.html?package=redaction)\n[![Npm Licence](https://img.shields.io/npm/l/redaction.svg)](https://www.npmjs.com/package/redaction)\n\n\n### Installation\n\nTo install the stable version:\n\n```bash\nnpm install --save redaction\n```\n\n\n## Overview\n\nIn large projects usage of the standard Redux approach becomes a headache because of of the huge amount of constants and pushing the dispatch across the entire application logic. Redaction comes to help us solve these problems.\n\n**Note:** Redaction is just wrapper over Redux, so it's not *reinventing the wheel*, it's **_sweet sugar_** :)\n\n**BEWARE:** If you use / or planning to use SSR in your project **DON'T USE** Redaction! Currently there are some approaches inside which prevents from doing with SSR in easy way.. If you still want to use it and get problems with SSR fill free to contact me \u003ca href=\"mailto:grammka@gmail.com\"\u003egrammka@gmail.com\u003c/a\u003e.\n\n\n## Redux approach\n\n##### `constants/todos.js`\n```js\nconst ADD_TODO = 'ADD_TODO'\n\nexport {\n  ADD_TODO\n}\n```\n\n##### `reducers/todos.js`\n```js\nimport { ADD_TODO } from 'constants/todos'\n\nconst initialState = {\n  todos: []\n}\n\nexport default (state = initialState, action) =\u003e {\n  switch (action.type) {\n\n    case ADD_TODO:\n      return {\n        ...state,\n        todos: [\n          ...state.todos,\n          action.payload\n        ]\n      }\n\n    default:\n      return state\n  }\n}\n```\n\n##### `actions/todos.js`\n```js\nimport { ADD_TODO } from 'constants/todos'\n\nexport const addTodo = (text) =\u003e (dispatch) =\u003e {\n  dispatch({\n    type: ADD_TODO,\n    payload: text\n  })\n}\n```\n\n##### `App.js`\n```js\nimport { connect } from 'react-redux'\nimport { addTODO } from 'actions/todos' \n\nconst App = ({ todos, addTodo }) =\u003e (\n  \u003cdiv\u003e\n    {\n      todos.map((text, index) =\u003e (\n        \u003cdiv key={index}\u003e{text}\u003c/div\u003e\n      ))\n    }\n    \u003cbutton onClick={() =\u003e addTodo('new todo name')}\u003eAdd\u003c/button\u003e\n  \u003c/div\u003e\n)\n\nconst mapStateToProps = (state) =\u003e ({\n  todos: state.todos,\n})\n\nconst mapDispatchToProps = (dispatch) =\u003e ({\n  addTodo: (text) =\u003e {\n    dispatch(addTodo(text))\n  }\n})\n\nexport default connect(mapStateToProps, mapDispatchToProps)(App)\n```\n\n\u003cbr /\u003e\n\n## Same with Redaction\n\n##### `reducers/todos.js`\n```js\nexport const initialState = {\n todos: []\n}\n\nexport const addTodo = (state, payload) =\u003e ({ \n  ...state, \n  todos: [ \n    ...state.todos, \n    payload \n  ]\n})\n```\n\n##### `actions/todos.js`\n```js\nimport { reducers } from 'core/reducers' // read docs to understand what core folder means\n\nexport const addTodo = (text) =\u003e {\n  reducers.todos.addTodo(text)\n}\n```\n\n`App.js`\n```\nimport actions from 'actions'\nimport { connect } from 'redaction' \n\nconst App = ({ todos }) =\u003e (\n  \u003cdiv\u003e\n    {\n      todos.map((text, index) =\u003e (\n        \u003cdiv key={index}\u003e{text}\u003c/div\u003e\n      ))\n    }\n    \u003cbutton onClick={() =\u003e actions.addTodo('new todo name')}\u003eAdd\u003c/button\u003e\n  \u003c/div\u003e\n)\n\nexport default connect({\n  todos: 'todos'\n})(App)\n```\n\n##### That's it! Nifty :) No constants! No dispatch!\n\n\n\u003cbr /\u003e\n\n## Usage\n\n##### `actions/users.js`\n```js\nimport reducers from 'core/reducers'\n\nexport const getAll = () =\u003e {\n  fetch({\n    endpoint: '/api/users',\n    method: 'GET'\n  })\n    .then((result) =\u003e {\n      reducers.users.put(result)\n    })\n}\n```\n\n##### `reducers/users.js`\n```js\nexport const initialState = {\n  list: [],\n}\n\nexport const put = (state, payload) =\u003e ({\n  ...state,\n  list: [\n    ...state.list,\n    payload,\n  ]\n}) \n```\n\n##### `core/store.js`\n\n```js\nimport { createStore, combineReducers } from 'redaction'\nimport { reducer as form } from 'redux-form'\nimport reducers from 'reducers'\n\nconst initialState = {}\n\nconst store = createStore({\n  reducers: {\n    ...combineReducers(reducers),\n    form,\n  },\n  initialState,\n})\n\nexport default store\n```\n\n##### `core/reducers.js`\n\n```js\nimport { wrapReducers } from 'redaction'\nimport reducers from 'reducers'\n\nexport default wrapReducers(reducers)\n```\n\n##### `components/Posts.js`\n\n```js\nimport React from 'react'\nimport { users } from 'actions'\n\nexport default class Posts extends React.Component {\n  componentWillMount() {\n    users.getAll()\n  }\n}\n```\n\n\u003cbr /\u003e\n\n## Features\n\n#### Connect\n\nThere is sugar to connect state to components nifty:\n\n```js\nimport React, { Component } from 'react'\nimport { connect } from 'redaction'\n\n// option 1\n@connect(state =\u003e ({\n  todos: state.todos.list,\n}))\n// option 2\n@connect({\n  todos: 'todos.list',\n})\n// option 3\n@connect({\n  todos: (state) =\u003e state.todos.list,\n})\nexport default class TodosList extends Component {}\n```\n\n\u003cbr /\u003e\n\n## Examples\n\n[Repo examples](https://github.com/pavelivanov/redaction/tree/master/examples/plain)\n\n\u003cbr /\u003e\n\n## Tests\n\nTo run tests:\n\n```\nnpm test\n```\n\n\u003cbr /\u003e\n\n## TODO\n\n- [ ] Support React hooks\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavelivanov%2Fredaction","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpavelivanov%2Fredaction","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavelivanov%2Fredaction/lists"}