{"id":13547946,"url":"https://github.com/luisvinicius167/dutier","last_synced_at":"2025-04-05T21:11:31.441Z","repository":{"id":57217275,"uuid":"93977628","full_name":"luisvinicius167/dutier","owner":"luisvinicius167","description":"The immutable, async and hybrid state management solution for Javascript applications. ","archived":false,"fork":false,"pushed_at":"2018-06-26T00:42:18.000Z","size":466,"stargazers_count":393,"open_issues_count":0,"forks_count":12,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-03-29T19:06:52.466Z","etag":null,"topics":["async","flux","javascript","minimal","react","redux","state-management"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luisvinicius167.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-11T02:47:28.000Z","updated_at":"2025-01-18T13:08:56.000Z","dependencies_parsed_at":"2022-08-28T21:40:31.291Z","dependency_job_id":null,"html_url":"https://github.com/luisvinicius167/dutier","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisvinicius167%2Fdutier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisvinicius167%2Fdutier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisvinicius167%2Fdutier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisvinicius167%2Fdutier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luisvinicius167","download_url":"https://codeload.github.com/luisvinicius167/dutier/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399886,"owners_count":20932880,"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","flux","javascript","minimal","react","redux","state-management"],"created_at":"2024-08-01T12:01:03.525Z","updated_at":"2025-04-05T21:11:31.417Z","avatar_url":"https://github.com/luisvinicius167.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","List"],"sub_categories":[],"readme":"\u003cimg width=\"200\" src=\"https://raw.githubusercontent.com/luisvinicius167/dutier/master/img/logo.png\"/\u003e \n\nThe 2kb immutable, async and universal state management solution for Javascript applications. \u003cbr/\u003e\n\n[![npm package](https://img.shields.io/badge/npm-1.1.4-blue.svg)](https://www.npmjs.com/package/dutier)\n[![CDN](https://img.shields.io/badge/cdn-1.1.4-ff69b4.svg)](https://unpkg.com/dutier@1.1.4)\n\n\n### Influences\nIt evolves on the ideas of [Redux](https://github.com/reactjs/redux).\n\n## Getting Started\n\n### Install\n* NPM: ``` npm install dutier ```\n* Yarn: ``` yarn add dutier ```\n* CDN: ```https://unpkg.com/dutier@1.1.4```\n\n### Features\n * immutable state\n * small 2kb minified\n * async by default\n * react provider\n * devtools\n * simple, small learning curve\n * no dependencies\n * promise based\n * Works well with any Javascript Framework\n * inspired by Redux\n \n ### Libraries \u0026 Add-ons:\n - :raised_hands: [**dutier-logger**](https://github.com/luisvinicius167/dutier-logger): Logger for Dutier inpired by Redux Logger. \n - :loop: [**react-dutier**](https://github.com/luisvinicius167/dutier/blob/master/README.md#react): React bindings for Dutier. Performant and flexible.\n \n ### Demos\n- :pencil: [React Todo with Dutier](https://codesandbox.io/s/3lov40m86)\n\n\n### Async Actions\nWith `Dutier` your `actions` are pure functions that returns a function with the dispatch method, that will dispatch a payload information about how to work with the state and the `dispatch` method always return new values based on your state.\n\nThe `dispatch` is async by default, then you can use `async/await` with `dispatch` method. \n\n```javascript\n  async function handler() {\n   const value = 1\n   await dispatch(action(value))  \n  } \n```\n\n### React \n* npm: ``` npm install react-dutier ```\n* yarn: ``` yarn add react-dutier ```\n\n```javascript\n/**\n * @name Provider\n * @description Provider your store to your application and \n * provides the store state and store dispatch method to the\n * first children Components level.\n * \n * @param {Object|Store} store The Store instance\n */\nimport React from 'react'\nimport { render } from 'react-dom'\nimport { Provider } from 'react-dutier'\nimport devtools from 'dutier/devtools'\nimport reducers from './reducers'\n\nconst store = devtools(createStore(reducers))\n\nconst Increment = ({ state, dispatch }) =\u003e \n  \u003cdiv\u003e \n    \u003cp\u003e Count: {state.count} \u003c/p\u003e \n    \u003cbutton onClick={() =\u003e dispatch(increment(1))}\u003e Increment\u003c/button\u003e\n  \u003c/div\u003e\n\nconst Decrement = ({ state, dispatch }) =\u003e \n  \u003cdiv\u003e \n    \u003cp\u003e Count: {state.count} \u003c/p\u003e \n    \u003cbutton onClick={() =\u003e dispatch(decrement(1))}\u003e Decrement\u003c/button\u003e\n  \u003c/div\u003e\n\nconst class App = () =\u003e \n  \u003cProvider store={store}\u003e\n    \u003cIncrement /\u003e\n    \u003cDecrement /\u003e\n  \u003c/Provider\u003e\n\nrender(\u003cApp/\u003e, document.getElementById('root'))\n\n/**\n * @name withStore\n * @description You can use withStore function to pass the \n * store state and disptach method as props to any Component \n * that you want.\n * \n * @param {Function}\n */\n import React, { Component } from 'react'\nimport { withStore } from 'react-dutier'\nimport App from 'containers/app'\n\nclass App extends Component {\n  componentDidMount(){\n    console.log(this.props) // logs: { state, dispatch }\n  }\n  \n  render(){\n    return (\u003cdiv /\u003e)\n  }\n}\n\nexport default withStore(App)\n```\n\n### Devtools\n```javascript\n/**\n * @name devtools\n * @description Dutier Version of Redux devtools.\n * @param { Store|Object } Dutier Store\n */\nimport { createStore } from 'dutier'\nimport devtools from 'dutier/devtools'\n\nconst store = devtools(createStore())\n```\n\n\u003cimg width=\"600\" src=\"https://raw.githubusercontent.com/luisvinicius167/dutier/master/img/devtools.png\" /\u003e\n\n### Universal\nThe application state is stored in an object tree inside a single store. Your actions will only dispatch information about how work with the state and then return new state values based on your state.\n\nThat's it!\n\n```javascript\nimport { createStore, applyMiddleware } from 'dutier'\nimport Logger from 'dutier-logger'\n\n/**\n * Reducer\n * The reducer state needs to be an Object\n * Each reducer receives the state as first argument\n * the action payload as second argument\n */\nconst initialState = { count: 1 }\nfunction reducer( state=initialState, { type, payload } ) {\n  switch (type) {\n    case 'INCREMENT':\n        return { count: state.count + payload }\n    default:\n      return state  \n  }\n}\n\n/**\n * Create the store and pass the reducers if you have.\n * Create store returns the functions: subscribe, dispatch and getState\n */\nconst store = createStore(reducer)\n\n/**\n * Apply your custom middleware function that\n * be called each time your store dispatch actions\n * You can use Dutier Logger library.\n * https://github.com/luisvinicius167/dutier-logger\n */\napplyMiddleware(Logger)\n\n\n/**\n * Actions are pure functions that return a new function\n * that will dispatch the payload information to Reducer\n */\n const increment = payload =\u003e dispatch =\u003e dispatch({ type: 'INCREMENT', payload })\n\n/**\n * Reducer\n * Each reducer receives the application state as first argument,\n * the action payload\n */\nconst initialState = { count: 1 }\nfunction reducer( state=initialState, { type, payload } ) {\n  switch (type) {\n    case 'INCREMENT':\n        return { count: state.count + payload }\n    default:\n      return state  \n  }\n}\n    \n/**\n * You can use store.subscribe() to update your UI in response to actions;\n * The subscribe are just be called if the state was changed.\n */\n  this.unsubscribe = store.subscribe( { type, state, payload } ) =\u003e {\n    console.log('Reducer new state value ', state, 'Store state: ', store.getState())\n  })\n\n\n/**\n * Use store.dispatch to return new values based on the state\n * tree. store.dispatch is async and returns a Promise with your action type and\n * the new state value.\n */\nstore.dispatch( increment( 1 ) )\n .then( ({ type, state }) =\u003e {\n   console.log(`The value is: ${getState().count}`) // 2\n })\n```\n\n\n### Simple and efficient API.\n\nstore.dispatch\n * Trigger an action to do something with the state. It's async by default and always return a promise \u003cbr\u003e \n that contains the action type and the new state value \n\n```javascript\n/**\n * @name dispatch\n * @description Trigger some action.\n * @param { Function } The function that return your action payload\n * @return { Promise } Return a Promise with the action payload\n */\n\n// You can receive the response of your action and do something, or not.\n// If you want, you can chain the dispatch Promises.\nstore.dispatch( increment(1) )\n\nstore\n  .dispatch( increment(1) )\n  .then( ({ type, state }) =\u003e {\n    console.log(type, state)\n  })\n```\n\nActions\n * Actions are async pure functions that returns a function with the dispatch method as first argument to dispatch the payload information to your reducers, for change the state.\n \n```javascript\nfunction increment( payload ) {\n  return dispatch =\u003e dispatch({ type: 'INCREMENT', payload })\n}\n```\n\n\nStore\n * Create your application store\n```javascript\n/**\n * @name createStore\n * You just can set your store state one time.\n * @param { Function } reducer Your store reducers\n */\n \nimport { createStore } from 'dutier'\n\nconst store = createStore([, ...reducers] )\n```\n\nGetting the store state\n * Get the current state value\n```javascript\n/**\n * @name getState\n * @description Get the current state value\n */\n\nstore.getState() // returns a copy of your store state { count: 1 }\n```\n\nCombine\n * Combine your store reducers\n```javascript\n/**\n * @name combine\n * @param { Function } Your reducers\n */\n \nimport { combine } from 'dutier'\n\nfunction reducer( state={ count: 1 }, { type, payload }) {\n  switch (type) {\n    case 'INCREMENT':\n      return { count: state.count + payload }\n    default:\n      return state  \n  }\n}\n\nfunction otherReducer( state={ counter: 1}, { type, payload } ) {\n  switch (type) {\n    case 'ADD':\n      return { count: payload }\n    default:\n      return state  \n  }\n}\n\ncombine( reducer, otherReducer, [, ...reducers ])\n```\n\nMiddleware\n * Call your custom middlewares\n```javascript\n/**\n * @name middleware\n * @param { Function } middleware Your middleware functions \n * that will be called each time your store dispatch actions\n * @param { Object } data Each middleware function receives a \n * data object with the properties action (your action payload), \n * oldState (the old state) and state (current state ) \n */\n  \nimport { applyMiddleware } from 'dutier'\n\nconst logger = data =\u003e console.log(data)\napplyMiddleware(logger [, ...middlewares ])\n```\n\nstore.subscribe\n * It will be called any time an action is dispatched and just if the state was changed.\n```javascript\n/**\n * @name subscribe\n * @param { handler } handler A callback function that will be triggered when\n * your state change\n */\n  \n  componentWillMount(){\n     // Subscribe to changes on your store, do something with the value.\n     this.unsubscribe = store.subscribe(( { type, state, payload } ) =\u003e {\n       this.setState( { count: store.getState().count } )\n     })\n  }\n  \n  componentWillUnmount() {\n    this.unsubscribe()\n  }\n```\n\nThat's all folks!\n\n\n#### License\nMIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluisvinicius167%2Fdutier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluisvinicius167%2Fdutier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluisvinicius167%2Fdutier/lists"}