{"id":21358310,"url":"https://github.com/bowheart/zedux","last_synced_at":"2025-07-13T00:33:46.276Z","repository":{"id":27627556,"uuid":"114693823","full_name":"bowheart/zedux","owner":"bowheart","description":"ATTENTION! This is the old repository. Zedux has moved to https://github.com/omnistac/zedux","archived":false,"fork":false,"pushed_at":"2023-04-10T12:11:47.000Z","size":5560,"stargazers_count":47,"open_issues_count":64,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-16T22:50:45.269Z","etag":null,"topics":["async","boilerplate","code-splitting","composable","easy","immutable","redux","selectors","state-machine","state-management","zero-configuration"],"latest_commit_sha":null,"homepage":"https://omnistac.github.io/zedux","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/bowheart.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-18T22:26:34.000Z","updated_at":"2023-10-08T04:09:21.000Z","dependencies_parsed_at":"2022-09-06T00:21:45.948Z","dependency_job_id":null,"html_url":"https://github.com/bowheart/zedux","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bowheart%2Fzedux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bowheart%2Fzedux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bowheart%2Fzedux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bowheart%2Fzedux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bowheart","download_url":"https://codeload.github.com/bowheart/zedux/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225028982,"owners_count":17409614,"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","boilerplate","code-splitting","composable","easy","immutable","redux","selectors","state-machine","state-management","zero-configuration"],"created_at":"2024-11-22T05:15:33.723Z","updated_at":"2024-11-22T05:15:34.181Z","avatar_url":"https://github.com/bowheart.png","language":"TypeScript","readme":"# [DEPRECATED]\n\nThis repo has moved to [`Omnistac/zedux`](https://github.com/omnistac/zedux).\n\n# Zedux\n\n[![Build Status](https://travis-ci.org/bowheart/zedux.svg?branch=master)](https://travis-ci.org/bowheart/zedux)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/0459ebf8444c36752eac/test_coverage)](https://codeclimate.com/github/bowheart/zedux/test_coverage)\n[![Maintainability](https://api.codeclimate.com/v1/badges/0459ebf8444c36752eac/maintainability)](https://codeclimate.com/github/bowheart/zedux/maintainability)\n[![npm](https://img.shields.io/npm/v/zedux.svg)](https://www.npmjs.com/package/zedux)\n\nOverpowered State Management for JavaScript.\n\n## Feature list of awesomeness\n\n- Composable stores\n- Built-in side effects model\n- Zero configuration\n- Reducer-driven state updates\n- Action creator utilities\n- Reducer creation utility\n- State machines\n- Action streams\n- Code splitting\n- Memoized selectors\n\n## Installation\n\nInstall using npm or yarn. E.g.:\n\n```bash\nnpm i zedux\n```\n\nOr include the appropriate unpkg build on your page (module exposed as `window.Zedux`):\n\n### Development\n\n```html\n\u003cscript src=\"https://unpkg.com/zedux/dist/zedux.js\"\u003e\u003c/script\u003e\n```\n\n### Production\n\n```html\n\u003cscript src=\"https://unpkg.com/zedux/dist/zedux.min.js\"\u003e\u003c/script\u003e\n```\n\n## Getting started\n\nTo learn by example, check out the [examples doc page](https://bowheart.github.io/zedux/docs/examples) or the [examples in the repo](https://github.com/bowheart/zedux/tree/master/examples).\n\nTo learn by getting dirty, have a play with [this codepen](https://codepen.io/bowheart/pen/MrKMmw?editors=0010).\n\nTo learn like a boss, check out the [tests](https://github.com/bowheart/zedux/tree/master/test).\n\nOr keep reading for a brief run-down:\n\n## Intro\n\n- **Flexible**\n\nThe core philosophy of Zedux. **Zedux apps can have many stores** and should. Each store is flexible, meaning it can adapt to its use case. Need more power? Build a reducer hierarchy. Need some simple, local state? Use zero config stores.\n\nApps of all sizes should be able to use Zedux comfortably.\n\n- **Composable**\n\nZedux takes Redux and dips it in React's composable architecture. Stores are composable, which means a store can control some or all of the state of another store. Stores therefore become building blocks of application state. Stateful components that expose a Zedux store can be simultaneously isolated and easily consumed/composed in any application.\n\n- **Opinionated but Configurable**\n\nSimplicity rules. Zedux stores require zero configuration to start. But they're flexible and powerful enough to move with you as your app's state demands increase. Zedux offers high-level apis for speed and simplicity, but also offers low-level escape hatches for everything.\n\n## Quick start\n\n\u003e This guide will assume basic knowledge of Redux, such as how to use reducers and the importance of immutability.\n\nAt the most basic level, Zedux is still Redux. A reducer hierarchy drives state creation and updates.\n\n```ts\nimport { createActor, createReducer, createStore } from 'zedux'\n\n/*\n  Meet your first Zedux store.\n  He's a fast, composable, predictable state container.\n  And the best part: He's all ready to go.\n*/\nconst store = createStore()\n\n/*\n  These are actors.\n  An actor is just a fancy action creator.\n*/\nconst increment = createActor('increment')\nconst decrement = createActor('decrement')\n\n/*\n  Zedux ships with a high-level api for reducer creation.\n  Here we delegate our actions to sub-reducers.\n*/\nconst counterReducer = createReducer(0) // 0 - the initial state\n  .reduce(increment, state =\u003e state + 1)\n  .reduce(decrement, state =\u003e state - 1)\n\n/*\n  So we said the store is all ready to go. And that's true.\n  But in Zedux, zero configuration is optional \u003cfireworks here\u003e.\n  We're not gonna use it here. We will in the next example.\n\n  Here we introduce our reducer hierarchy to the store.\n*/\nstore.use(counterReducer)\n\n// Zedux calls this function every time the store's state changes.\nstore.subscribe((newState, oldState) =\u003e {\n  console.log(`counter went from ${oldState} to ${newState}`)\n})\n\nstore.dispatch(increment()) // counter went from 0 to 1\nstore.dispatch(increment()) // counter went from 1 to 2\nstore.dispatch(decrement()) // counter went from 2 to 1\n```\n\nIf you know Redux, almost all of this will seem familiar. At this point, you should know enough to get started using Zedux. But don't worry, there's a ton of cool stuff we haven't covered.\n\nHere's a small taste of what's in store (hah):\n\n## Zero configuration\n\nZedux stores are so dynamic, you can just create one and go. Zero config should feel just like using React's `useState` hook. In fact, use cases are very similar.\n\nHere's what the above counter example looks like if we leverage zero configuration:\n\n```ts\nimport { createStore } from 'zedux'\n\n// In zero config mode, we typically hydrate the store initially\nconst store = createStore().hydrate(0) // set initial state to 0\n\n// That's it!\nstore.setState(store.getState() + 1) // sets store state to 1\nstore.setState(store.getState() + 1) // sets store state to 2\n```\n\nDid you see that? Zedux state updates are fully synchronous. The second `getState()` call is able to access the new state. This is possible because Zedux does not have a middleware layer.\n\nNow, if you're familiar with React's `useState` hook, you'll know there's a better way to update state based on a previous state:\n\n```ts\nimport { createStore } from 'zedux'\n\nconst store = createStore().hydrate(0)\n\nstore.setState(state =\u003e state + 1) // sets store state to 1\nstore.setState(state =\u003e state + 1) // sets store state to 2\n```\n\nThat's right, you can pass a function to `setState()` which will be called with the current state. But we just created the same function twice! Let's fix that:\n\n```ts\nconst increment = state =\u003e state + 1\n\nstore.setState(increment)\nstore.setState(increment)\n```\n\nIn Zedux, this is called the Inducer Pattern. Inducers are just state updater functions named like action creators but implemented like reducers. While often not needed, this pattern can help reduce complexity in larger zero-config stores.\n\nYou can give `setState()` a partial state object. Zedux deeply merges it into the rest of the state for you:\n\n```ts\nimport { createStore } from 'zedux'\n\nconst store = createStore().hydrate({ a: { b: 1 }, c: 2 })\n\nstore.setState({ c: 3 })\n// { a: { b: 1 }, c: 3 }\nstore.setState(state =\u003e ({ a: { b: state.a.b + 1 } }))\n// { a: { b: 2 }, c: 3 }\n```\n\nNote that `store.hydrate()` does _not_ merge state:\n\n```ts\nstore.hydrate({ c: 3 }) // { c: 3 } (oops)\n```\n\n\u003e You may have noticed that the branch nodes of our state trees are all plain objects. But Zedux can actually be taught to understand any hierarchical data type. Immutable fans rejoice and check out the guide on [configuring the hierarchy](https://bowheart.github.io/zedux/docs/guides/configuringTheHierarchy).\n\n### But what about time travel??\n\nNo worries! Zedux translates every pseudo-action into a serializable action that a store's effect subscribers can plug in to. `store.hydrate()`, `store.setState()`, `store.use()`, and actions dispatched to child stores will all find a way to notify a store's effect subscribers of a serializable action that can be used to reproduce the state update. In short, you never have to worry about whether a state update is reproducible; Zedux has you covered.\n\n## Store composition\n\nToo good to be true? Think again. The store composition model of Zedux is unprecedented and extremely powerful. The Zedux store's disposable and highly performant nature combined with its uncanny time traveling ability will make you weep. With joy, of course.\n\n```ts\nimport { createStore } from 'zedux'\n\nconst childStore = creatStore().hydrate('child state!')\nconst parentStore = createStore({\n  child: childStore\n})\n\nparentStore.getState()\n// { child: 'child state!' }\n```\n\nZedux keeps the child's state in sync with the parent. Every time the child's state changes, the parent's state changes. Actions dispatched to the parent store are forwarded on to all its child stores. Calling `setState()` and `hydrate()` on the parent store can also reach in to its child stores and update them.\n\n## State machines\n\nDon't get too excited. But yes, state machines are very powerful and yes, Zedux includes a basic implementation.\n\nA state machine is just a graph. The possible states are the nodes of the graph. The possible transitions between states are directed edges connecting the nodes.\n\n```ts\nimport { createActor, createMachine } from 'zedux'\n\n// Define some actions that will transition the machine\nconst press = createActor('press')\nconst timer = createActor('timer')\n\n/*\n  Once we have our states, we create the machine by defining\n  how the machine transitions from one state to the next.\n\n  A machine is just a fancy reducer.\n*/\nconst doorMachine = createMachine('open') // set initial state\n  .addTransition('open', press, 'closing')\n  .addTransition('closing', press, 'opening')\n  .addTransition('closing', timer, 'closed')\n  .addTransition('closed', press, 'opening')\n  .addTransition('opening', press, 'closing')\n  .addTransition('opening', timer, 'open')\n\n// Since doorMachine is a reducer, it's easy to test\ndoorMachine(open.type, closing()) // closing - valid transition\ndoorMachine(closing.type, open()) // closing - invalid transition\ndoorMachine(opening.type, open()) // open - valid transition\n```\n\nZedux machines (and all Zedux reducers) can also be passed directly to React's `useReducer`. They don't have to be used in a Zedux store.\n\n## Conclusion\n\nZedux offers all the benefits of the global, singleton model, but also the isolation and reusability of component-bound (fractal) stores. It offers all the power of Redux' reducer-driven state updates and the lightweight simplicity of React's `useState` hook.\n\nZedux apps will be able to mix and match approaches, adapting to every stateful need with the appropriate amount of power and/or simplicity.\n\nThe composable nature of Zedux makes it especially useful in feature-based, micro-frontend, or otherwise code-split architectures.\n\nAt this point you should have a pretty good idea of what Zedux is all about. Check out the [full documentation](https://bowheart.github.io/zedux/docs/getting-started/quick-start) for the rest of the awesomeness.\n\n## Official packages\n\n- [React Zedux](https://github.com/bowheart/react-zedux) - Official React bindings for Zedux.\n- [Zedux Immer](https://github.com/bowheart/zedux-immer) - Official Immer bindings for Zedux.\n\n## Contributing\n\nAll contributions on any level are so overwhelmingly welcome. Just jump right in. Open an issue. For PRs, just use prettier like a human and keep tests at 100% (branches, functions, lines, everything 100%, plz). Let's make this awesome!\n\nBugs can be submitted to https://github.com/bowheart/zedux/issues\n\n## License\n\nThe MIT License.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbowheart%2Fzedux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbowheart%2Fzedux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbowheart%2Fzedux/lists"}