{"id":13452574,"url":"https://github.com/facebookarchive/redux-react-hook","last_synced_at":"2025-03-23T19:34:34.121Z","repository":{"id":46170347,"uuid":"155604462","full_name":"facebookarchive/redux-react-hook","owner":"facebookarchive","description":"React Hook for accessing state and dispatch from a Redux store","archived":true,"fork":false,"pushed_at":"2021-11-09T17:28:27.000Z","size":6790,"stargazers_count":2158,"open_issues_count":12,"forks_count":103,"subscribers_count":36,"default_branch":"main","last_synced_at":"2024-10-30T02:30:57.519Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/facebookarchive.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-31T18:20:11.000Z","updated_at":"2024-09-10T07:06:10.000Z","dependencies_parsed_at":"2022-09-13T03:02:26.352Z","dependency_job_id":null,"html_url":"https://github.com/facebookarchive/redux-react-hook","commit_stats":null,"previous_names":["facebookincubator/redux-react-hook"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebookarchive%2Fredux-react-hook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebookarchive%2Fredux-react-hook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebookarchive%2Fredux-react-hook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebookarchive%2Fredux-react-hook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/facebookarchive","download_url":"https://codeload.github.com/facebookarchive/redux-react-hook/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245159516,"owners_count":20570396,"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":[],"created_at":"2024-07-31T07:01:27.889Z","updated_at":"2025-03-23T19:34:33.676Z","avatar_url":"https://github.com/facebookarchive.png","language":"TypeScript","readme":"# redux-react-hook\n\n\u003e React hook for accessing mapped state and dispatch from a Redux store.\n\n[![Build Status](https://img.shields.io/travis/com/facebookincubator/redux-react-hook.svg)](https://travis-ci.com/facebookincubator/redux-react-hook)\n[![NPM](https://img.shields.io/npm/v/redux-react-hook.svg)](https://www.npmjs.com/package/redux-react-hook)\n[![Bundle Size](https://img.shields.io/bundlephobia/minzip/redux-react-hook.svg)](https://bundlephobia.com/result?p=redux-react-hook@latest)\n\n# This project has been DEPRECATED\n\nWith the release of the [hooks API in react-redux 7](https://react-redux.js.org/api/hooks), this project has become redundant.\n\n## Table of Contents\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Usage](#usage)\n  - [`StoreContext`](#storecontext)\n  - [`useMappedState(mapState, equalityCheck?)`](#usemappedstatemapstate-equalitycheck)\n  - [`useDispatch()`](#usedispatch)\n  - [`create(options?)`](#createoptions)\n- [Example](#example)\n- [FAQ](#faq)\n- [Related projects](#related-projects)\n- [Thanks](#thanks)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Install\n\n```bash\n# Yarn\nyarn add redux-react-hook\n\n# NPM\nnpm install --save redux-react-hook\n```\n\n## Quick Start\n\n```tsx\n//\n// Bootstrap your app\n//\nimport {StoreContext} from 'redux-react-hook';\n\nReactDOM.render(\n  \u003cStoreContext.Provider value={store}\u003e\n    \u003cApp /\u003e\n  \u003c/StoreContext.Provider\u003e,\n  document.getElementById('root'),\n);\n```\n\n```tsx\n//\n// Individual components\n//\nimport {useDispatch, useMappedState} from 'redux-react-hook';\nimport shallowEqual from 'shallowequal';\n\nexport function DeleteButton({index}) {\n  // Declare your memoized mapState function\n  const mapState = useCallback(\n    state =\u003e ({\n      canDelete: state.todos[index].canDelete,\n      name: state.todos[index].name,\n    }),\n    [index],\n  );\n\n  // Get data from and subscribe to the store\n  const {canDelete, name} = useMappedState(mapState, shallowEqual);\n\n  // Create actions\n  const dispatch = useDispatch();\n  const deleteTodo = useCallback(\n    () =\u003e\n      dispatch({\n        type: 'delete todo',\n        index,\n      }),\n    [index],\n  );\n\n  return (\n    \u003cbutton disabled={!canDelete} onClick={deleteTodo}\u003e\n      Delete {name}\n    \u003c/button\u003e\n  );\n}\n```\n\n## Usage\n\nNOTE: React hooks require `react` and `react-dom` version `16.8.0` or higher.\n\n### `StoreContext`\n\nBefore you can use the hook, you must provide your Redux store via `StoreContext.Provider`:\n\n```tsx\nimport {createStore} from 'redux';\nimport {StoreContext} from 'redux-react-hook';\nimport reducer from './reducer';\n\nconst store = createStore(reducer);\n\nReactDOM.render(\n  \u003cStoreContext.Provider value={store}\u003e\n    \u003cApp /\u003e\n  \u003c/StoreContext.Provider\u003e,\n  document.getElementById('root'),\n);\n```\n\nYou can also use the `StoreContext` to access the store directly, which is useful for event handlers that only need more state when they are triggered:\n\n```tsx\nimport {useContext} from 'react';\nimport {StoreContext} from 'redux-react-hook';\n\nfunction Component() {\n  const store = useContext(StoreContext);\n  const onClick = useCallback(() =\u003e {\n    const value = selectExpensiveValue(store.getState());\n    alert('Value: ' + value);\n  });\n  return \u003cdiv onClick={onClick} /\u003e;\n}\n```\n\n### `useMappedState(mapState, equalityCheck?)`\n\nRuns the given `mapState` function against your store state, similar to\n`mapStateToProps`. Unlike `mapStateToProps`, however, the result of your\n`mapState` function is compared for reference equality (`===`) by default. To\nuse shallow equal comparison, pass in a comparision function as the second\nparameter.\n\n```tsx\nconst state = useMappedState(mapState);\n```\n\nYou can use props or other component state in your `mapState` function. It must be memoized with `useCallback`, because `useMappedState` will infinitely recurse if you pass in a new mapState function every time.\n\n```tsx\nimport {useMappedState} from 'redux-react-hook';\n\nfunction TodoItem({index}) {\n  // Note that we pass the index as a dependency parameter -- this causes\n  // useCallback to return the same function every time unless index changes.\n  const mapState = useCallback(state =\u003e state.todos[index], [index]);\n  const todo = useMappedState(mapState);\n\n  return \u003cli\u003e{todo}\u003c/li\u003e;\n}\n```\n\nIf you don't have any inputs (the second argument to `useCallback`) pass an empty array `[]` so React uses the same function instance each render. You could also declare `mapState` outside of the function, but the React team does not recommend it, since the whole point of hooks is to allow you to keep everything in the component.\n\nThe second parameter to `useMappedState` is used to determine if a new result from the `mapState` function is the same as the previous result, in which case your component will not be re-rendered. Prior to v4.0.1, this was hard-coded to a shallow equality check. Starting in v4.0.1, `equalityCheck` defaults to reference equality (using `===`). To restore the old behavior, which is particularly useful when you are returning an object, you can use the [`shallowequal`](https://www.npmjs.com/package/shallowequal) module:\n\n```tsx\nimport {useMappedState} from 'redux-react-hook';\nimport shallowEqual from 'shallowequal';\n\nfunction TodoItem({index}) {\n  // Note that we pass the index as a dependency parameter -- this causes\n  // useCallback to return the same function every time unless index changes.\n  const mapState = useCallback(\n    state =\u003e ({\n      todo: state.todos[index],\n      totalCount: state.todos.length,\n    }),\n    [index],\n  );\n  const {todo, totalCount} = useMappedState(mapState, shallowEqual);\n\n  return \u003cli\u003e{todo}\u003c/li\u003e;\n}\n```\n\nTo avoid specifying the comparison function on every call to `useMappedState`, you can provide the defaultEqualityCheck option to [`create()`](#create). The `shallowEqual` function from [`fast-equals`](https://www.npmjs.com/package/fast-equals) is another good option, as it handles shallow comparisons of `Map`s and `Set`s as well as objects.\n\nNOTE: Every call to `useMappedState` will subscribe to the store. If the store updates, though, your component will only re-render once. So, calling `useMappedState` more than once (for example encapsulated inside a custom hook) should not have a large performance impact. If your measurements show a performance impact, you can switch to returning an object instead.\n\n### `useDispatch()`\n\nSimply returns the dispatch method.\n\n```tsx\nimport {useDispatch} from 'redux-react-hook';\n\nfunction DeleteButton({index}) {\n  const dispatch = useDispatch();\n  const deleteTodo = useCallback(() =\u003e dispatch({type: 'delete todo', index}), [\n    index,\n  ]);\n\n  return \u003cbutton onClick={deleteTodo}\u003ex\u003c/button\u003e;\n}\n```\n\n### `create(options?)`\n\nCreates an instance of Redux React Hooks with a new `StoreContext`. The above functions are just exports of the default instance. You may want to create your own instance if:\n\n1. You want better type safety without annotating every callsite. Creating your own instance ensures that the types are the same for all consumers. See the example for more info.\n2. You want to provide a default implementation of `equalityCheck` for all calls to `mapState`\n3. You have multiple Redux stores (this is not common)\n\n```tsx\n// MyStoreHooks.js\n\nimport {create} from 'redux-react-hook';\n\nexport const {StoreContext, useDispatch, useMappedState} = create();\n```\n\n```tsx\n// MyStoreHooks.ts\n\nimport {create} from 'redux-react-hook';\n\n// Example in TypeScript where you have defined IState and Action\nexport const {StoreContext, useDispatch, useMappedState} = create\u003c\n  IState,\n  Action,\n  Store\u003cIState, Action\u003e\n\u003e();\n```\n\n`create` takes an optional `options` object with the following options:\n\n- `defaultEqualityCheck` - the default implementation of `equalityCheck` to use in `useMappedState`, defaults to refence equality (`===`)\n\nTo restore the pre v4.0.1 comparison behavior, for example:\n\n```tsx\nimport {create} from 'redux-react-hook';\nimport shallowEqual from 'shallow-equal';\n\n// Example in TypeScript where you have defined IState and Action\nexport const {StoreContext, useDispatch, useMappedState} = create\u003c\n  IState,\n  Action,\n  Store\u003cIState, Action\u003e\n\u003e({defaultEqualityCheck: shallowEqual});\n```\n\n## Example\n\nYou can try out `redux-react-hook` right in your browser with the [Codesandbox example](https://codesandbox.io/s/github/ianobermiller/redux-react-hook-example).\n\nTo run the example project locally:\n\n```bash\n# In one terminal, run `yarn start` in the root to rebuild the library itself\ncd ./redux-react-example\nyarn start\n\n# In another terminal, run `yarn start` in the `example` folder\ncd example\nyarn start\n```\n\n## FAQ\n\n### Is it typed with TypeScript/Flow?\n\nOne of the nice benefits of using hooks is that they are easier to type and less prone to trouble than higher-order components, especially when you are using multiple hooks (vs multiple HOCs). `redux-react-hook` comes with both [TypeScript definitions](https://github.com/facebookincubator/redux-react-hook/blob/master/src/index.d.ts) and [Flow types](https://github.com/facebookincubator/redux-react-hook/blob/master/src/index.js.flow), both of which should work out of the box when installing with npm/yarn.\n\n### How does this compare to React Redux?\n\n`redux-react-hook` has not been battle and perf-tested, so we don't recommend replacing [`react-redux`](https://github.com/reduxjs/react-redux) just yet. React Redux also guarantees that [data flows top down](https://medium.com/@kj_huang/implementation-of-react-redux-part-2-633441bd3306), so that child components update after their parents, which the hook does not.\n\n### How do I fix the error \"Too many re-renders. React limits the number of renders to prevent an infinite loop.\"\n\nYou're not memoizing the `mapState` function. Either declare it outside of your\nstateless functional component or wrap it in `useCallback` to avoid creating a\nnew function every render.\n\n### How can I use a selector creator, like in reselect?\n\nIf you want to [share a selector with props across multiple component instances](https://github.com/reduxjs/reselect#sharing-selectors-with-props-across-multiple-component-instances), create the selector in `useMemo` to ensure it has one copy per instance and use it directly in `useMappedState`.\n\n```tsx\nfunction TodoList({listID}) {\n  // useMemo will execute the function makeGetVisibleTodos once per component\n  const getVisibleTodos = useMemo(makeGetVisibleTodos, []);\n  const todos = useMappedState(\n    useCallback(\n      // Note that you shouldn't pass the entire props list, since every time\n      // useCallback is recreated, useMappedState will resubscribe\n      state =\u003e getVisibleTodos(state, {listID}),\n      [listID, getVisibleTodos],\n    ),\n  );\n}\n```\n\n## Related projects\n\nHere are some other projects that are adding hooks for Redux:\n\n- [React Redux](https://react-redux.js.org/api/hooks) has hooks in version 7.1 and above\n- [`use-substate`](https://github.com/philipp-spiess/use-substate)\n- [`react-use-redux`](https://github.com/martynaskadisa/react-use-redux)\n- [`react-use-dux`](https://github.com/richardpj/react-use-dux)\n- [`react-use-redux-state`](https://github.com/pinyin/react-use-redux-state)\n\n## Thanks\n\nSpecial thanks to @sawyerhood and @sophiebits for writing most of the initial implementation! This repo was setup with the help of the excellent [`create-react-library`](https://www.npmjs.com/package/create-react-library).\n\n## Contributing\n\nContributions are definitely welcome! Check out the [issues](https://github.com/facebookincubator/redux-react-hook/issues)\nfor ideas on where you can contribute. See the [CONTRIBUTING.md](CONTRIBUTING.md) file for more details.\n\n## License\n\nMIT © Facebook Inc.\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebookarchive%2Fredux-react-hook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffacebookarchive%2Fredux-react-hook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebookarchive%2Fredux-react-hook/lists"}