{"id":26581509,"url":"https://github.com/type-hub/re-action","last_synced_at":"2025-07-01T05:32:52.778Z","repository":{"id":278260927,"uuid":"935028813","full_name":"type-hub/re-action","owner":"type-hub","description":"🛠️ Your toolbox for working with React's useReducer hook 🪝","archived":false,"fork":false,"pushed_at":"2025-03-20T09:32:50.000Z","size":68,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-20T10:25:41.249Z","etag":null,"topics":["actions","context","hooks","react","react-hooks","reducer","state-management","type","type-safe","usereducer-hook"],"latest_commit_sha":null,"homepage":"","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/type-hub.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":"2025-02-18T19:39:55.000Z","updated_at":"2025-03-20T09:32:56.000Z","dependencies_parsed_at":"2025-02-18T21:25:24.919Z","dependency_job_id":"84f03032-3a78-4261-8d4b-c68a8b3b4d54","html_url":"https://github.com/type-hub/re-action","commit_stats":null,"previous_names":["type-hub/re-action"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/type-hub%2Fre-action","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/type-hub%2Fre-action/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/type-hub%2Fre-action/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/type-hub%2Fre-action/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/type-hub","download_url":"https://codeload.github.com/type-hub/re-action/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245067579,"owners_count":20555596,"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":["actions","context","hooks","react","react-hooks","reducer","state-management","type","type-safe","usereducer-hook"],"created_at":"2025-03-23T07:20:03.863Z","updated_at":"2025-07-01T05:32:52.766Z","avatar_url":"https://github.com/type-hub.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ere-action\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cb\u003ere-action\u003c/b\u003e provides a structured way to work with useReducer by offering a collection of hooks, utilities, and component creators. It streamlines action binding, context management, and reducer setup, making state management more intuitive and scalable.\n\u003c/p\u003e\n\n## 💡 Motivation\n\nIn modern React development, managing complex state has become increasingly challenging. While the useReducer Hook offers a way to handle state logic, developers often encounter several pain points:\n\n- **Verbose Syntax**: Manually dispatching actions can lead to boilerplate code, making components harder to read and maintain.\n- **Scalability Issues**: As applications grow, setting up and managing reducers and contexts can become cumbersome, hindering scalability.\n- **TypeScript Integration**: Ensuring type safety with useReducer requires additional effort, which can be error-prone and time-consuming.\n\nRecognizing these challenges, re-action was developed to streamline state management in React applications. By offering a suite of hooks, utilities, and component creators, it simplifies action binding, context management, and reducer setup. This not only reduces boilerplate but also enhances code readability and maintainability, allowing developers to focus on building features rather than managing state intricacies.\n\n## 🚀 Benefits\n\n- **Small Size**: just **2KB** minified\n- **Full TS support**\n- **No more dispatch calls, just actions**\n- Simplified `useReducer`: Cleaner syntax for state management\n- Performance-optimized for efficiency\n- Gradual Refactoring Support: Eases transitions in legacy code\n\n## 📦 Installation\n\n```sh\nnpm install @type-hub/re-action\n```\n\n## 📚 Documentation\n\n- [📚 Vocabulary](#-vocabulary)\n- [🛠 Sandbox examples](#-sandbox-examples)\n- [📘 API Reference](#-api-reference)\n  - [🪝 useBoundActions](#useBoundActions)\n  - [🪝 useBoundReducer](#useBoundReducer)\n  - [🏗️ createActionContext](#createActionContext)\n  - [🏗️ createReducerContext](#createReducerContext)\n  - [🏭 createReducerStore](#createReducerStore)\n  - [🔧 createActionCreators](#createActionCreators)\n  - [🔧 contextFactory](#contextFactory)\n  - [🔍 GetActionTypes](#GetActionTypes)\n\n## 📚 Vocabulary\n\n**Action**\n\n```ts\ntype ACTION = { type: string; payload: any }\n```\n\nAn object representing a state change request in useReducer. It consists of a type field (a string identifier) and an optional payload containing additional data.\n\n**ActionCreator**\n\n```ts\ntype ActionCreator\u003cPayload\u003e = (payload: Payload) =\u003e {\n  type: string\n  payload: Payload\n}\n```\n\nA function that generates an Action object. It takes a payload as an argument and returns an object with a predefined type and the provided payload. This helps streamline action creation and reduces boilerplate.\n\n**ActionCreators**\n\n```ts\ntype ActionCreators = Record\u003cstring, ActionCreator\u003cany\u003e\u003e\n```\n\nAn object mapping action names (strings) to ActionCreator functions. This provides a structured way to define multiple action creators in a single place, making it easier to dispatch actions without manually constructing them.\n\n## 🛠 Sandbox Examples\n\n- [🪝 useBoundActions](https://stackblitz.com/edit/vitejs-vite-pbfaydmg?embed=1\u0026file=src%2Fpages%2FPageA.tsx)\n- [🪝useBoundReducer](https://stackblitz.com/edit/vitejs-vite-pbfaydmg?embed=1\u0026file=src%2Fpages%2FPageB.tsx)\n- [🏗️ createActionContext](https://stackblitz.com/edit/vitejs-vite-pbfaydmg?embed=1\u0026file=src%2Fpages%2FPageC.tsx)\n- [🏗️ createReducerContext](https://stackblitz.com/edit/vitejs-vite-pbfaydmg?embed=1\u0026file=src%2Fpages%2FPageD.tsx)\n- [🏭 createReducerStore](https://stackblitz.com/edit/vitejs-vite-pbfaydmg?embed=1\u0026file=src%2Fpages%2FPageE.tsx)\n- [🔧 createActionCreators](https://stackblitz.com/edit/vitejs-vite-pbfaydmg?file=src%2Fstore%2Factions.ts)\n- [🔍 GetActionTypes](https://stackblitz.com/edit/vitejs-vite-pbfaydmg?file=src%2Fstore%2Freducer.ts)\n\n# 📘 API Reference\n\n## 🪝 Hooks\n\n### `useBoundActions()`\n\n```ts\nconst boundActions = useBoundActions(dispatch, actionsCreators)\n```\n\n**useBoundActions** is a React hook that binds action creators to a **dispatch** function, ensuring actions are dispatched directly when called. It memoizes the bound actions to maintain reference stability and prevent unnecessary re-renders. By dynamically mapping action creators to **dispatch**, it simplifies state management in a Redux-like setup.\n\n### `useBoundReducer()`\n\n```ts\nconst boundActions = useBoundReducer(reducer, actionsCreators, initState)\n```\n\n**useBoundReducer** is a React hook that combines **useReducer** with **useBoundActions**, providing a stateful reducer along with action creators that are automatically bound to **dispatch**. It ensures that actions are dispatched seamlessly when called, simplifying state updates while maintaining reference stability. The hook returns the current **state**, the **bound action creators**, and the **raw dispatch** function for flexibility.\n\n## 🏗️ Setup\n\n### `createActionContext()`\n\n```ts\nconst { TestProvider, useTest, useTestBoundActions } = createActionContext(\n  actionsCreators,\n  \"Name\",\n)\n```\n\n**setupActions** is a utility that creates a context-based action bincreateActionContextn the application. The returned object includes a React **context for actions** and a **dynamically named hook** (use[DisplayName]BindedActions) for **binding actions** to a given **dispatch** function.\n\n### `createReducerContext()`\n\n```ts\nconst {\n  TestActionsProvider,\n  TestStateProvider,\n  useTestBoundActions,\n  useTestReducer,\n  useTestState,\n} = createReducerContext(reducer, actionCreators, \"DisplayName)\n```\n\n**createReducerContext** is a utility that generates a **named reducer context**, along with **state** and **action contexts**, enabling structured state management. It creates a dynamically named hook (use[DisplayName]Reducer) that initializes a reducer with bound actions while also exposing separate contexts for state and actions. This ensures encapsulated, context-aware state management within a React application.\n\n## 🏭 Component Creators\n\n### `createReducerStore()`\n\n```ts\nconst { TestProvider, useTestState, useTestBoundActions } = create(\n  reducer,\n  actionCreators,\n  \"DisplayName,\n)\n```\n\n**create** is a utility that sets up a fully encapsulated state management system using React context and a reducer. It dynamically generates a **provider component** ([DisplayName]Provider) to manage state and actions, along with **hooks** (use[DisplayName]State and use[DisplayName]Actions) for accessing them. This allows for a structured and reusable approach to managing state across a React application.\n\n## 🔧 Utils\n\n### `createActionCreators()`\n\n```ts\nexport const actionCreators = createActionCreators({\n  increment: (amount: number) =\u003e amount,\n  decrement: (amount: number) =\u003e amount,\n})\n\ndeclare const testAction: any\n\nif (actionCreators.increment.match(testAction)) {\n  testAction // { type: \"increment\"; payload: number; }\n}\n```\n\nThis function **generates action creators** from a given **lookup object** containing functions. It iterates over the keys of the provided function lookup, wrapping each function to create a standardized action object containing a type derived from the key and a payload produced by invoking the corresponding function. This approach ensures type safety by inferring input parameters and return types, making it easier to define consistent and predictable action creators for state management in a functional and type-driven way.\n\n#### `.match()`\n\nEach generated **actionCreator** includes a **.match(action)** method, which checks whether the given action matches the type of actions created by that action creator.\n\n```ts\nconst actionCreators = createActionCreators([\"a\", \"b\", \"c\"])\n\nactionCreators.a.match({ type: \"a\" }) // true\nactionCreators.b.match({ type: \"b\" }) // true\nactionCreators.c.match({ type: \"c\" }) // true\n```\n\n#### `.type`\n\nEach generated **actionCreator** includes a **type** field, which contains the type of the action created by that action creator.\n\n```ts\nconst actionCreators = createActionCreators([\"a\", \"b\", \"c\"])\n\nactionCreators.a.type // \"a\"\nactionCreators.b.type // \"b\"\nactionCreators.c.type // \"c\"\n```\n\n## `contextFactory()`\n\n```ts\nconst contextName = \"Test\"\nconst { TestProvider, useTest } = contextFactory\u003cState, typeof contextName\u003e(\n  contextName,\n)\n```\n\nThis utility function creates a strongly-typed React context factory, generating a **custom provider** and a **corresponding hook** for accessing the context value. It ensures that consumers of the hook cannot access the context outside of its provider, throwing an error if misused. The provider is wrapped in React.memo to optimize re-renders, and both the **provider and hook names** are **dynamically derived** from an optional **display name**. This approach simplifies context creation by enforcing type safety and reducing boilerplate when managing shared state in a React application.\n\n## 🔍 Type Utils\n\n### `GetActions\u003cT\u003e`\n\n```ts\nexport const actionCreators = createActionCreators({\n  increment: (amount: number) =\u003e amount,\n  decrement: (amount: number) =\u003e amount,\n})\n\ntype Actions = GetActions\u003ctypeof actionCreators\u003e\n// | { type: \"increment\"; payload: number; }\n// | { type: \"decrement\"; payload: number; }\n\nconst reducer = (state: State, action: Actions): State =\u003e {\n  /* ... */\n  return state\n}\n```\n\n**GetActions** extracts the **union** of all possible **action objects** returned by an action creators object. It iterates over each key in AC, retrieves the return type of the corresponding function, and combines them into a single union type.\n\n### `GetActionTypes\u003cT\u003e`\n\n```ts\nexport const actionCreators = createActionCreators({\n  increment: (amount: number) =\u003e amount,\n  decrement: (amount: number) =\u003e amount,\n})\n\ntype ActionTypes = GetActionTypes\u003ctypeof actionCreators\u003e\n// \"increment\" | \"decrement\"\n```\n\n**GetActionTypes** extracts the **union** of all possible **action types** returned by an action creators object. It iterates over each key in AC, retrieves the return type of the corresponding function, and combines them into a single union type.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftype-hub%2Fre-action","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftype-hub%2Fre-action","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftype-hub%2Fre-action/lists"}