{"id":13401058,"url":"https://github.com/CharlesStover/reactn","last_synced_at":"2025-03-14T06:32:10.931Z","repository":{"id":33062522,"uuid":"150817942","full_name":"CharlesStover/reactn","owner":"CharlesStover","description":"React, but with built-in global state management.","archived":true,"fork":false,"pushed_at":"2023-02-14T03:24:19.000Z","size":3083,"stargazers_count":1893,"open_issues_count":43,"forks_count":85,"subscribers_count":34,"default_branch":"master","last_synced_at":"2024-10-16T21:47:11.741Z","etag":null,"topics":["babel","babeljs","javascript","js","npm","react","reactjs","state-management","travis","travis-ci","travisci","typescript","webpack"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/reactn","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/CharlesStover.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"github":"CharlesStover"}},"created_at":"2018-09-29T02:54:42.000Z","updated_at":"2024-10-16T15:33:29.000Z","dependencies_parsed_at":"2023-11-29T08:23:58.067Z","dependency_job_id":null,"html_url":"https://github.com/CharlesStover/reactn","commit_stats":null,"previous_names":["quisido/reactn","charlesstover/reactn"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CharlesStover%2Freactn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CharlesStover%2Freactn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CharlesStover%2Freactn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CharlesStover%2Freactn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CharlesStover","download_url":"https://codeload.github.com/CharlesStover/reactn/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243538057,"owners_count":20307100,"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":["babel","babeljs","javascript","js","npm","react","reactjs","state-management","travis","travis-ci","travisci","typescript","webpack"],"created_at":"2024-07-30T19:00:58.263Z","updated_at":"2025-03-14T06:32:10.917Z","avatar_url":"https://github.com/CharlesStover.png","language":"TypeScript","readme":"# ReactN\n\n[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=ReactN%20offers%20global%20state%20management%20baked%20into%20React!\u0026url=https://github.com/CharlesStover/reactn\u0026via=CharlesStover\u0026hashtags=react,reactjs,javascript,typescript,webdev,webdevelopment)\n[![version](https://img.shields.io/npm/v/reactn.svg)](https://www.npmjs.com/package/reactn)\n[![minzipped size](https://img.shields.io/bundlephobia/minzip/reactn.svg)](https://www.npmjs.com/package/reactn)\n[![downloads](https://img.shields.io/npm/dt/reactn.svg)](https://www.npmjs.com/package/reactn)\n\nReactN is an extension of React that includes global state management. It treats\nglobal state as if it were built into React itself -- without the boilerplate\nof third party libraries.\n\n[![banner](https://user-images.githubusercontent.com/343837/53267742-fe3f4900-3698-11e9-82fd-3c3a1decb7fd.png)](https://www.npmjs.com/package/reactn)\n\nFor support, reach out to us on the\n[Reactiflux Discord channel #reactn](https://discord.gg/Tae4vuX).\n\n💗 this project?\n[Become a sponsor.](https://github.com/sponsors/CharlesStover)\n\n## Install\n\n- `npm install reactn` or\n- `yarn add reactn`\n\n## Features\n\n### No boilerplate\n\nFor function components, `import { useGlobal } from \"reactn\";` to harness the\npower of React Hooks!\n\nFor class components, simply change `import React from \"react\";` to\n`import React from \"reactn\";`, and your React class components will have global\nstate built in!\n\nIf you prefer class decorators, you can continue to\n`import React from \"react\";` for your components and additionally\n`import reactn from \"reactn\";` for access to the `@reactn` decorator!\n\n### Intuitive\n\n#### Function components\n\nGlobal state in function components behaves almost identically to local state.\n\nYou use `[ global, setGlobal ] = useGlobal()` to access the entire global state\nobject.\n\nYou use `[ value, setValue ] = useGlobal(property)` where `property` is the\nproperty of the global state you want to get and set.\n\nGlobal reducers in function components behaves almost identically to local\nreducers.\n\nYou use `dispatch = useDispatch(reducerFunction)` to mimic the behavior of\n`useReducer`, where instead of providing an initial state, the state of the\nreducer is the ReactN global state object.\n\nYou use `dispatch = useDispatch(reducerName)` to use a reducer that was added\nby the `addReducer` helper function.\n\nYou use `dispatch = useDispatch(reducerFunction, property)` or\n`[ value, dispatch ] = useDispatch(reducerFunction, property)` to apply a\nreducer specifically to a global state property. This is very similar to\nReact's native `useReducer` functionality.\n\n#### Class components\n\nGlobal state in class components behaves exactly like local state!\n\nYou use `this.global` and `this.setGlobal` to get and set the global state.\n\nYou use `this.dispatch.reducerName()` to dispatch to a reducer that was added\nby the `addReducer` helper function.\n\nThe `@reactn` decorator allows you to convert classes that extend\n`React.Component` to ReactN global state components.\n\n#### Map state to props\n\nIf you prefer Redux's `connect` functionality, pure functions, or are dealing\nwith deeply nested objects, a\n[`withGlobal` higher-order component](#withglobal) is also available.\n\n## Table of contents\n\n- [Install](#install)\n- [Features](#features)\n  - [No boilerplate](#no-boilerplate)\n  - [Intuitive](#intuitive)\n- [Getting started](#getting-started)\n  - [Managing multiple states](#managing-multiple-states)\n  - [Initializing your state](#initializing-your-state)\n  - [TypeScript support](#typescript-support)\n  - [Developer tools](#developer-tools)\n  - [Examples](#examples)\n    - [Class components](#class-components)\n    - [Class components (with decorator)](#class-components-with-decorator)\n    - [Function components](#function-components-1)\n    - [Helper functions](#helper-functions)\n      - [addCallback](#addcallback)\n      - [addReducer](#addreducer)\n      - [getDispatch](#getdispatch)\n      - [getGlobal](#getglobal)\n      - [removeCallback](#removecallback)\n      - [resetGlobal](#resetglobal)\n      - [setGlobal](#setglobal)\n      - [useDispatch](#usedispatch)\n      - [useGlobal](#useglobal)\n      - [withGlobal](#withglobal)\n      - [withInit](#withinit)\n- [Known issues](#known-issues)\n- [Terminology](#terminology)\n- [Frequently asked questions](https://github.com/CharlesStover/reactn/blob/master/FAQ.md)\n- [Support](#support)\n\n## Getting started\n\n### Managing multiple states\n\n**This README is for managing a single global state.** This is ideal for most\napplications. If you are using concurrent server-side rendering or otherwise\nwant to work with multiple global states, follow the README for the\n[Provider](https://github.com/CharlesStover/reactn/blob/master/Provider.md)\ncomponent, which allows you to limit a ReactN state to a React Context.\n\nIf you are unsure whether or not you need multiple global states, then you do\nnot need multiple global states.\n\n### Initializing your state\n\nYou can initialize your global state using the `setGlobal` helper function. In\nmost cases, you do not want to initialize your global state in a component\nlifecycle method, as the global state should exist before your components\nattempt to render.\n\nIt is recommended that you initialize the global state just prior to mounting\nwith `ReactDOM`.\n\n```javascript\nimport React, { setGlobal } from 'reactn';\nimport ReactDOM from 'react-dom';\nimport App from './App';\n\n// Set an initial global state directly:\nsetGlobal({\n  cards: [],\n  disabled: false,\n  initial: 'values',\n  x: 1,\n});\n\nReactDOM.render(\u003cApp /\u003e, document.getElementById('root'));\n```\n\n### TypeScript support\n\nReactN supports TypeScript out of the box! It is written entirely in TypeScript.\nThis gives it powerful intellisense, auto-complete, and error-catching abilities.\n\nTypeScript can maintain inferred global state and reducer shape of a\n[Providers](https://github.com/CharlesStover/reactn/blob/master/Provider.md).\nUnfortunately, without your help, it cannot track the shape of the \"default\"\nglobal state -- the one manipulated by the `setGlobal` and `addReducer` helper\nfunctions.\n\nIn order to tell TypeScript the shape of your global state when you are not using\na Provider, create a file at `src/global.d.ts` with the following contents:\n\n```javascript\nimport \"reactn\";\n\ndeclare module \"reactn/default\" {\n\n  export interface Reducers {\n\n    append: (\n      global: State,\n      dispatch: Dispatch,\n      ...strings: any[]\n    ) =\u003e Pick\u003cState, \"value\"\u003e;\n\n    increment: (\n      global: State,\n      dispatch: Dispatch,\n      i: number,\n    ) =\u003e Pick\u003cState, \"count\"\u003e;\n\n    doNothing: (\n      global: State,\n      dispatch: Dispatch,\n    ) =\u003e null;\n  }\n\n  export interface State {\n    count: number;\n    value: string;\n  }\n}\n```\n\nIn the above file, we extend the `Reducers` and `State` interfaces in the\n`\"reactn/default\"` file. While you will never use `\"reactn/default\"` in\nyour code, ReactN will use it to determine the shape of the default\nglobal state.\n\nThe above example will add `append`, `increment`, and `doNothing` to your\n`useDispatch` and `this.dispatch` auto-completion and typing. The parameters\nand return values will also be correctly typed. In addition, it will also\nadd `count` and `value` to your `useGlobal` and `this.global` auto-competion\nwith the appropriate types as well.\n\n### Developer tools\n\nReactN is compatible with the\n[Redux DevTools extension](https://github.com/zalmoxisus/redux-devtools-extension#installation).\n\n- Install the Redux DevTools extension to your browser or environment.\n- Install the `redux` package to your project via `npm` or `yarn`. This is used\n  to create a middleware Redux store for the Redux DevTools extension.\n  - You do _not_ have to import or use the `redux` package anywhere in your\n    project.\n  - You do _not_ need to create a Redux store, reducer, or actions.\n  - `redux` is just a peer dependency. It will be managed automatically.\n- Follow the instructions on the\n  [ReactN DevTools README](https://github.com/CharlesStover/reactn-devtools#readme).\n\n### Examples\n\n#### Class components\n\nBy importing React from `reactn` instead of `react`, you bake global state\ndirectly into the React namespace. As a result, `Component` and `PureComponent`\nwill have access to the `global` and `dispatch` member variables and\n`setGlobal` method.\n\n```javascript\nimport React from 'reactn'; // \u003c-- reactn\nimport Card from '../card/card';\n\n// Render all cards in the global state.\nexport default class Cards extends React.PureComponent {\n  componentDidMount() {\n    // Hydrate the global state with the response from /api/cards.\n    this.setGlobal(\n      // Despite fetch returning a Promise, ReactN can handle it.\n      fetch('/api/cards')\n        .then((response) =\u003e response.json())\n\n        // Set the global `cards` property to the response.\n        .then((cards) =\u003e ({ cards }))\n\n        // Fail gracefully, set the global `error`\n        //   property to the caught error.\n        .catch((err) =\u003e ({ error: err }))\n    );\n  }\n\n  render() {\n    // For each card in the global state, render a Card component.\n    // this.global returns the global state,\n    //   much the same way this.state returns the local state.\n    return (\n      \u003cdiv\u003e\n        {this.global.cards.map((card) =\u003e (\n          \u003cCard key={card.id} {...card} /\u003e\n        ))}\n      \u003c/div\u003e\n    );\n  }\n}\n```\n\n#### Class components (with decorator)\n\nBy importing React and ReactN separately, the React namespace remains\nunchanged. You can inject ReactN's global functionality into your vanilla React\ncomponent by using the `@reactn` decorator imported from the `reactn` package.\n\n```javascript\nimport React from 'react';\nimport reactn from 'reactn'; // \u003c-- reactn\nimport Card from '../card/card';\n\n// Render all cards in the global state.\n@reactn\nexport default class Cards extends React.PureComponent {\n  componentDidMount() {\n    // Hydrate the global state with the response from /api/cards.\n    this.setGlobal(\n      // Despite fetch returning a Promise, ReactN can handle it.\n      fetch('/api/cards')\n        .then((response) =\u003e response.json())\n\n        // Set the global `cards` property to the response.\n        .then((cards) =\u003e ({ cards }))\n\n        // Fail gracefully, set the global `error`\n        //   property to the caught error.\n        .catch((err) =\u003e ({ error: err }))\n    );\n  }\n\n  render() {\n    // For each card in the global state, render a Card component.\n    // this.global returns the global state,\n    //   much the same way this.state returns the local state.\n    return (\n      \u003cdiv\u003e\n        {this.global.cards.map((card) =\u003e (\n          \u003cCard key={card.id} {...card} /\u003e\n        ))}\n      \u003c/div\u003e\n    );\n  }\n}\n```\n\n#### Function components\n\nUsing [React Hooks](https://reactjs.org/docs/hooks-intro.html), you can harness\n`useGlobal` to access the global state.\n\n```javascript\nimport React, { useGlobal } from 'reactn'; // \u003c-- reactn\nimport Card from '../card/card';\n\n// Render all cards in the global state.\nconst Cards = () =\u003e {\n  // Use the hook to get all cards in the global state.\n  //   setCards is not used in this example.\n  const [cards, setCards] = useGlobal('cards');\n\n  // For each card in the global state, render a Card component.\n  return (\n    \u003cdiv\u003e\n      {cards.map((card) =\u003e (\n        \u003cCard key={card.id} {...card} /\u003e\n      ))}\n    \u003c/div\u003e\n  );\n};\n\nexport default Cards;\n```\n\nYou may also use the `useDispatch` hook analogously to the `useReducer` hook by\nproviding a function to `useDispatch`.\n\n```javascript\nimport React, { useDispatch } from 'reactn'; // \u003c-- reactn\n\nconst incrementReducer = (global, dispatch, action) =\u003e ({\n  count: global.count + action.amount,\n});\n\nconst decrementReducer = (global, dispatch, action) =\u003e ({\n  count: global.count - action.amount,\n});\n\nconst MyComponent = () =\u003e {\n  const increment = useDispatch(incrementReducer);\n  const decrement = useDispatch(decrementReducer);\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e increment({ amount: 1 })}\u003eAdd 1\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e increment({ amount: 3 })}\u003eAdd 3\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e decrement({ amount: 5 })}\u003eSubtract 5\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n\nexport default MyComponent;\n```\n\nBy providing a second parameter to `useDispatch` that is the key of the global\nstate, the return value of that reducer will set that property of the global\nstate. This allows you to write your reducers similar to React's `useReducer`.\n\n```javascript\nimport React, { useDispatch } from 'reactn'; // \u003c-- reactn\n\nconst incrementReducer = (count, action) =\u003e count + action.amount;\n\nconst decrementReducer = (count, action) =\u003e count - action.amount;\n\nconst MyComponent = () =\u003e {\n  const increment = useDispatch(incrementReducer, 'count');\n  const decrement = useDispatch(decrementReducer, 'count');\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e increment({ amount: 1 })}\u003eAdd 1\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e increment({ amount: 3 })}\u003eAdd 3\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e decrement({ amount: 5 })}\u003eSubtract 5\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n\nexport default MyComponent;\n```\n\n#### Helper functions\n\n##### addCallback\n\nUse `addCallback` to execute a function whenever the state changes. The return\nvalue of the callback will update the global state, so be sure to only return\n`undefined` or `null` if you do not want the global state to change. Be aware\nthat always returning a new state value will result in an infinite loop, as the\nnew global state will trigger the very same callback.\n\nThe only parameter is the callback function.\n\n```javascript\nimport { addCallback, setGlobal } from 'reactn';\n\n// Every time the global state changes, this function will execute.\naddCallback((global, dispatcherMap, stateChange) =\u003e {\n  alert(`The new value is ${global.value}!`);\n\n  // If the global state was changed to 1, change it to 2.\n  if (global.value === 1) {\n    return { value: 2 };\n  }\n\n  // If the global state is anything other than 1, don't change it.\n  return null;\n});\n\nsetGlobal({ value: 1 });\n// The new value is 1!\n// The new value is 2!\n```\n\nThe return value of `addCallback` is a function that, when executed, removes\nthe callback.\n\n```javascript\nimport { addCallback, setGlobal } from 'reactn';\n\nconst removeAlert = addCallback((global) =\u003e {\n  alert(global.value);\n});\n\n// The callback causes an alert on global state change:\nsetGlobal({ value: 1 }); // 1\nsetGlobal({ value: 2 }); // 2\n\n// No longer execute the callback.\nremoveAlert();\n\n// No alerts:\nsetGlobal({ value: 3 });\nsetGlobal({ value: 4 });\n```\n\n##### addReducer\n\nUse `addReducer` to add a reducer to your global state.\n\nThe first parameter is the name of your reducer. You will access your reducer\nby this name. `this.dispatch.reducerName` or `useDispatch(\"reducerName\")`.\n\nThe second parameter is the reducer function. The reducer function that you\n_write_ has at least two parameters: first, the global state; second, a map of\nyour reducers. The third and onward parameters are the arguments that you pass\nwhen dispatching. The reducer function that you _use_ when dispatching does not\ncontain the global state or map of reducers. Those are prefixed for you\nautomatically.\n\n```javascript\nimport { addReducer, setGlobal, useDispatch, useGlobal } from 'reactn';\n\n// Initialize the global state with the value 0.\nsetGlobal({ value: 0 });\n\n// When the increment reducer is called, increment the global value by X.\naddReducer('increment', (global, dispatch, x = 1) =\u003e ({\n  value: global.value + x,\n}));\n\nfunction MyComponent() {\n  const increment = useDispatch('increment');\n  const [value] = useGlobal('value');\n  return (\n    \u003c\u003e\n      The value is{' '}\n      \u003cbutton\n        onClick={() =\u003e {\n          // Increment from 0 to 1.\n          // (the default value of the reducer is 1)\n          if (value === 0) {\n            increment();\n          }\n\n          // Increment from 1 to 5.\n          else if (value === 1) {\n            increment(4);\n          }\n        }}\n        value={value}\n      /\u003e\n    \u003c/\u003e\n  );\n}\n```\n\nFor a class component, the analogous method is\n`this.dispatch.increment(value)`.\n\nThe `dispatch` parameter on a reducer allows you to write \"sagas,\" or a single\nreducer that dispatches other reducers.\n\n```javascript\n// add(1)\naddReducer('add', (global, dispatch, i) =\u003e ({\n  x: global.x + i,\n}));\n\n// subtract(2)\naddReducer('subtract', (global, dispatch, i) =\u003e ({\n  x: global.x - i,\n}));\n\n// addSubtract(1, 2)\naddReducer('addSubtract', async (global, dispatch, i, j) =\u003e {\n  await dispatch.add(i);\n  await dispatch.subtract(j);\n});\n```\n\n##### addReducers\n\n`addReducers` accepts an object where the keys are reducer names and the values\nare reducers. `addReducers` is just a convenient shorthand for calling\n`addReducer` multiple times.\n\n##### getDispatch\n\nUse `getDispatch` to return an object of the global dispatch functions. You\nonly want to use this in helper libraries, and _not_ in Components. Components\nshould use `useDispatch` or `this.dispatch`.\n\n`getDispatch` has no parameters.\n\n```javascript\nimport { getDispatch } from 'reactn';\n\n// Access this.dispatch.reducerName outside of a Component.\nclass HelperLibrary {\n  getDispatcherFunction() {\n    return getDispatch().reducerName;\n  }\n}\n```\n\n##### getGlobal\n\nUse `getGlobal` to return a current snapshot of the global state. You only want\nto use this in helper libraries, and _not_ in Components. Components should use\n`useGlobal` or `this.global` to ensure that they re-render when the global\nstate changes. `getGlobal` will not cause a Component reliant on the global\nstate to re-render, nor will it cause a library function to re-execute. It does\nnothing more than return a current snapshot of the global state.\n\n`getGlobal` has no parameters.\n\n```javascript\nimport { getGlobal } from 'reactn';\n\n// Access this.global.value outside of a Component.\nclass HelperLibrary {\n  getGlobalValue() {\n    return getGlobal().value;\n  }\n}\n```\n\n##### removeCallback\n\nUse `removeCallback` to remove a callback that was added via `addCallback`. The\ncallback must be the same _function reference_. This is equivalent to executing\nthe return value of `addCallback`.\n\nThe only parameter is the callback function itself.\n\n```javascript\nimport { addCallback, removeCallback, setGlobal } from 'reactn';\n\nfunction alertCallback(global) {\n  alert(global.value);\n}\n\naddCallback(alertCallback);\n\n// Alerts the global state value:\nsetGlobal({ value: 1 }); // 1\nsetGlobal({ value: 2 }); // 2\n\n// Remove the alert callback:\nremoveCallback(alertCallback);\n\n// No alerts:\nsetGlobal({ value: 3 });\nsetGlobal({ value: 4 });\n```\n\n##### resetGlobal\n\nUse `resetGlobal` to reset the global state. This resets all state values,\nincluding callbacks, property listeners, and reducers.\n\nThere are no parameters.\n\n```javascript\nimport { getGlobal, resetGlobal, setGlobal } from 'reactn';\n\n// Set the value.\nsetGlobal({ value: 1 });\n\n// Get the value.\nalert(getGlobal().value); // 1\n\n// Reset the global state.\nresetGlobal();\n\n// Get the value.\nalert(getGlobal().value); // undefined\n```\n\n##### setGlobal\n\nUse `setGlobal` to initialize or update your global state. This is analogous to\ncalling `this.setGlobal` in a class component or `useGlobal()[1]` in a\nfunction component.\n\nThe first parameter is merged into the global state in the same way a class\ncomponent's `this.setGlobal` merges its first parameter into the local state.\n\nThe optional second parameter is a callback.\n\n`setGlobal` with a new global state:\n\n```javascript\nimport { setGlobal } from 'reactn';\n\n// Set loading to true.\nsetGlobal({\n  loading: true,\n});\n```\n\n`setGlobal` with a new global state and a callback:\n\n```javascript\nimport { setGlobal } from 'reactn';\n\n// Set loading to true.\nsetGlobal(\n  {\n    loading: true,\n  },\n\n  // After it is set, assert that loading is true.\n  (global) =\u003e {\n    assert(global.loading === true);\n  }\n);\n```\n\n##### useDispatch\n\n_Requires React \u003e= 16.8.0_\n\nThe `useDispatch` helper function is a React Hook analogous to the `useReducer`\nhook built into React itself. `useDispatch` will dispatch a global reducer that\nhas been added to ReactN via the [`addReducer`](#addreducer),\n[`addReducers`](#addreducers), or [`withInit`](#withinit) helper functions or a\nglobal reducer that you specify inline as a parameter.\n\n###### useDispatch()\n\n`useDispatch()` with no parameters will return a map of all of your global\nreducers.\n\n```javascript\nimport { useDispatch } from 'reactn';\n\nfunction MyComponent() {\n  const dispatch = useDispatch();\n  dispatch.add(1);\n  dispatch.substract(2);\n  return null;\n}\n```\n\n###### useDispatch(Function)\n\n`useDispatch(f)` allows you to define your global reducer inline. This method\nis particularly useful if you prefer to import your reducers as needed or keep\nyour singleton reducers with the components that use them.\n\n```javascript\nimport React, { useDispatch, useGlobal } from 'reactn';\n\nfunction MyComponent() {\n  const [count] = useGlobal('count');\n  const add = useDispatch((global, _dispatch, n) =\u003e ({\n    count: global.count + n,\n  }));\n  return \u003cbutton onClick={() =\u003e add(1)}\u003e{count}.\u003c/span\u003e;\n}\n```\n\n###### useDispatch(Function, keyof State)\n\n`useDispatch(f, \"property\")` allows you to define your global property reducer\ninline. A property reducer changes only one property of the global state, which\ncan greatly simplify your reducer logic.\n\n```javascript\nimport React, { useDispatch, useGlobal } from 'reactn';\n\nfunction MyComponent() {\n  const [count] = useGlobal('count');\n  const add = useDispatch((count, n) =\u003e count + n, 'count');\n  return \u003cbutton onClick={() =\u003e add(1)}\u003e{count}.\u003c/span\u003e;\n}\n```\n\n###### useDispatch(keyof Reducers)\n\n`useDispatch(\"reducerName\")` allows you to dispatch a global reducer.\n\n```javascript\nimport React, { useDispatch, useGlobal } from 'reactn';\n\nfunction MyComponent() {\n  const [count] = useGlobal('count');\n  const add = useDispatch('add');\n  return \u003cbutton onClick={() =\u003e add(1)}\u003e{count}.\u003c/span\u003e;\n}\n```\n\n##### useGlobal\n\n_Requires React \u003e= 16.8.0_\n\n`useGlobal` is a React Hook analogous to the `useState` Hook built into React\nitself. `useGlobal` returns the global state or parts thereof.\n\n###### useGlobal()\n\n`useGlobal()` with no parameters will return the entire global state object and\na function for changing properties of the global state.\n\nThe `setGlobal` function returned by `useGlobal` is analogous to the\n[`setGlobal`](#setglobal) helper function and `this.setGlobal` class method.\n\n```javascript\nimport React, { useGlobal } from \"reactn\";\n\nfunction MyComponent() {\n  const [ global, setGlobal ] = useGlobal();\n  const generateNumber = () =\u003e {\n    setGlobal(g =\u003e ({\n      generations: g.generations + 1,\n      myNumber: Math.floor(Math.random() * 100),\n    });\n  };\n  return (\n    \u003cbutton onClick={generateNumber}\u003e\n      #{global.generations}: {global.myNumber}\n    \u003c/button\u003e\n  );\n}\n```\n\n###### useGlobal(keyof State)\n\n`useGlobal(\"property\")` returns a specific global state property and a function\nfor updating that property.\n\n```javascript\nimport React, { useGlobal } from 'reactn';\n\nconst getRandomNumber = () =\u003e Math.floor(Math.random() * 100);\n\nfunction MyComponent() {\n  const [myNumber, setMyNumber] = useGlobal('myNumber');\n  return \u003cbutton onClick={() =\u003e setMyNumber(getRandomNumber())}\u003e{myNumber}\u003c/button\u003e;\n}\n```\n\n##### withGlobal\n\nUse `withGlobal` to return a higher-order component to convert global state\nvalues into props. This is highly analogous to `react-redux`'s `connect`\nfunction.\n\nThe first parameter is a function for getting global state values.\n\nThe second parameter is a function for setting global state values (similar to\n`dispatch`).\n\n```javascript\nimport React, { withGlobal } from 'reactn';\n\n// A button that displays the value and, when clicked, increments it.\nfunction MyComponent(props) {\n  return (\n    \u003c\u003e\n      My value is \u003cbutton onClick={props.incrementValue} value={props.value} /\u003e\n    \u003c/\u003e\n  );\n}\n\nexport default withGlobal(\n  // Set the `value` prop equal to the global state's `value` property.\n  (global) =\u003e ({\n    value: global.value,\n  }),\n\n  // Important Note: This is not the setGlobal helper function.\n  // Set the `incrementValue` prop to a function that increments the global\n  //   state's `value` property.\n  (setGlobal) =\u003e ({\n    incrementValue: () =\u003e {\n      // Important Note: This is not the setGlobal helper function.\n      // This is the parameter referenced 4 lines up.\n      setGlobal((global) =\u003e ({\n        value: global.value + 1,\n      }));\n    },\n  })\n)(MyComponent);\n```\n\n##### withInit\n\nIn some cases (such as when using Next.js), you may be unable to run a setup\nscript prior to your ReactN components mounting. In order to instantiate your\nglobal state and reducers prior to mounting, you may use the `withInit` Higher\nOrder Component. This HOC will await the setting of your global state before\nmounting the provided Lower Order Component (e.g. `\u003cApp /\u003e`).\n\n```javascript\nimport React, { useDispatch, useGlobal, withInit } from 'reactn';\n\nconst INITIAL_REDUCERS = {\n  addOne: ({ count }) =\u003e ({\n    count: count + 1,\n  }),\n};\n\nconst INITIAL_STATE = {\n  count: 0,\n};\n\nexport default withInit(\n  INITIAL_STATE,\n  INITIAL_REDUCERS\n)(function App() {\n  const addOne = useDispatch('addOne');\n  const [count] = useGlobal('count');\n  return \u003cbutton onClick={addOne}\u003eCount: {count}\u003c/button\u003e;\n});\n```\n\n## Known issues\n\n- `super(props)` is incompatible with TypeScript. #126\n- Components re-render once per changed subscribed property. #129\n- Class components use `componentWillUpdate` without the `UNSAFE_` prefix. #134\n- Class components are incompatible with Providers in newer versions of React.\n  #132\n\n## Terminology\n\nReactN strictly maintains accurate terminology for its data structures. The\nmajority of ReactN's data structures are meant to be black box to simplify the\nuser experience, only referenced by name in the package's code. They are\noutlined here for transparency and to ease community contributions.\n\n### Dispatcher\n\nWhen you pass a reducer to ReactN via [`addReducer`](#addreducer),\n[`addReducers`](#addreducers), [`useDispatch`](#usedispatch), or\n[`withInit`](#withinit), ReactN returns a dispatcher.\n\nA dispatcher is a function that wraps a reducer, passing the global state and\nglobal reducers as parameters tying its return value to the global state.\nDispatchers and reducers have a 1-to-1 relationship and are tightly bound to\neach other.\n\nIn documentation, dispatchers are often referred to as reducers to decrease the\ncognitive overhead and conceptually strengthen their 1-to-1 relationship.\n\nFor example, an \"add\" reducer may be defined as follows:\n\n```javascript\nfunction add(global, _dispatch, n) {\n  return { count: global.count + n };\n}\n```\n\nWhen you call this reducer, you only need to call `add(1)`. This difference in\ncall signature is because you are calling the _dispatcher_.\n\nA dispatcher, in pseudo-code, conceptually looks as follows:\n\n```javascript\nfunction dispatchAdd(n) {\n  const { dispatchers, set, state } = globalStateManager;\n  const newGlobalState = add(state, dispatchers, n);\n  return set(newGlobalState);\n}\n```\n\n### Global state manager\n\nThe global state manager is the core object that powers ReactN. It maintains\nthe state, global dispatchers, and subscriptions.\n\n#### Default global state manager\n\nThe default global state manager is the global state manager used by all of\nReactN _unless otherwise specified_. To specify a different global state\nmanager, you must use a\n[Provider](https://github.com/CharlesStover/reactn/blob/master/Provider.md).\n\nReactN Components and Hooks will attempt to find a global state manager via\nthe Context. If one does not exist via Context, it will fallback to the default\nglobal state manager.\n\n### Reducer\n\nA reducer is a function that accepts the current global state, a map of all\nglobal reducers, and any number of additional parameters. A reducer returns a\nchange to the global state. It does not need to return the entire new global\nstate. It only needs to return key-value pairs of changed properties.\n\nAn example \"add\" reducer may be defined as follows:\n\n```javascript\nfunction add(global, _dispatch, n) {\n  return { count: global.count + n };\n}\n```\n\nA reducer may be asynchronous (return a Promise) and asynchronously dispatch\nother reducers. You can use a reducer that dispatches other reducers to create\na \"saga\" of state changes.\n\n```javascript\nasync function mySaga(global, dispatch, shouldMultiply) {\n  if (global.count \u003c 0) {\n    await dispatch.add(1);\n  }\n  await dispatch.subtract(2);\n  if (shouldMultiply) {\n    await dispatch.multiply(3);\n  }\n}\n\nmySaga(true); // shouldMultiply = true\n```\n\n#### Property reducer\n\nA property reducer is a reducer that only changes one property. They only\nreceive that property's value as a parameter instead of the entire global state\nobject, and they do not receive the dispatch object as a parameter at all.\n\nAn example \"add\" property reducer may be defined as follows:\n\n```javascript\nfunction add(count, n) {\n  return count + n;\n}\n```\n\nYou must specify the property when _using_ a property reducer. Property\nreducers cannot be added to or remembered by the global state manager.\n\n```javascript\nimport React, { useDispatch, useGlobal } from 'reactn';\n\nfunction add(count, n) {\n  return count + n;\n}\n\nfunction MyComponent() {\n  const [count] = useGlobal('count');\n  // Use the \"add\" property reducer on the \"count\" property.\n  const dispatch = useDispatch(add, 'count');\n  return \u003cbutton onClick={() =\u003e dispatch(1)}\u003e{count}\u003c/button\u003e;\n}\n```\n\n## Sponsor\n\nIf you are a fan of this project, you may\n[become a sponsor](https://github.com/sponsors/CharlesStover)\nvia GitHub's Sponsors Program.\n\n## Support\n\nFor support, reach out to us on the\n[Reactiflux Discord channel #reactn](https://discord.gg/Tae4vuX).\n\n[![chat](https://img.shields.io/discord/102860784329052160.svg)](https://discord.gg/Tae4vuX)\n","funding_links":["https://github.com/sponsors/CharlesStover"],"categories":["Uncategorized","Utilities","TypeScript","Explanation of each State Management","React [🔝](#readme)","List"],"sub_categories":["Uncategorized","State Management","Reactn"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCharlesStover%2Freactn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCharlesStover%2Freactn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCharlesStover%2Freactn/lists"}