{"id":27957964,"url":"https://github.com/ngneat/react-rxjs","last_synced_at":"2025-05-07T18:15:39.976Z","repository":{"id":43697793,"uuid":"409323322","full_name":"ngneat/react-rxjs","owner":"ngneat","description":"🔌 \"Plug and play\" for Observables in React Apps!","archived":false,"fork":false,"pushed_at":"2022-05-03T13:07:56.000Z","size":995,"stargazers_count":36,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-07T18:15:31.707Z","etag":null,"topics":["react","reacthooks","rxjs"],"latest_commit_sha":null,"homepage":"https://www.netbasal.com","language":"TypeScript","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/ngneat.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":"2021-09-22T19:01:05.000Z","updated_at":"2025-01-16T23:22:26.000Z","dependencies_parsed_at":"2022-09-17T00:00:43.761Z","dependency_job_id":null,"html_url":"https://github.com/ngneat/react-rxjs","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Freact-rxjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Freact-rxjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Freact-rxjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Freact-rxjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ngneat","download_url":"https://codeload.github.com/ngneat/react-rxjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252931507,"owners_count":21827112,"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":["react","reacthooks","rxjs"],"created_at":"2025-05-07T18:15:35.369Z","updated_at":"2025-05-07T18:15:39.967Z","avatar_url":"https://github.com/ngneat.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n \u003cimg width=\"20%\" height=\"20%\" src=\"logo.png\"\u003e\n\u003c/p\u003e\n\n\u003e \"Plug and play\" for RxJS Observables in React Apps!\n\n[![@ngneat/react-rxjs](https://github.com/ngneat/react-rxjs/actions/workflows/ci.yml/badge.svg)](https://github.com/ngneat/react-rxjs/actions/workflows/ci.yml)\n![commitizen](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square)\n![PRs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)\n![coc-badge](https://img.shields.io/badge/codeof-conduct-ff69b4.svg?style=flat-square)\n![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e5079.svg?style=flat-square]https://github.com/semantic-release/semantic-release)\n![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square]https://github.com/prettier/prettier)\n\n\n```bash\nnpm install @ngneat/react-rxjs\n```\n\n## useObservable\n\nEver had an Observable holding data that you need to maintain in the state of your React App? This hook bridges that gap.\n\nIt receives an Observable, subscribes to it, and stores the current version in a react state, ensuring that it persists between re-renders.\n\nNote that you can use it multiple times, with various Observables.\n\n```tsx\nimport { interval } from 'rxjs';\nimport { take } from 'rxjs/operators';\nimport { useObservable } from '@ngneat/react-rxjs';\n\nconst interval$ = interval(1000);\n\nfunction CounterComponent() {\n  const [counter] = useObservable(interval$);\n  const [counter, { error, completed, subscription }] = useObservable(interval$.pipe(take(3)));\n\n  return \u003ch1\u003e{counter}\u003c/h1\u003e;\n}\n```\n\n`useObservable` can take the initial value as the second parameter - `useObservable(source$, initialValue)`. If the source fires synchronously immediately (like in a `BehaviorSubject`), the value will be used as the initial value.\n\nYou can also pass a dependencies:\n\n```tsx\nimport { useObservable } from '@ngneat/react-rxjs';\n\nconst SomeComponent = ({ id }: { id: string }) =\u003e {\n  const [state] = useObservable(getStream$(id), { deps: [id] })\n\n  return state;\n}\n```\n\n\n## useUntilDestroyed\n\nThe `useUntilDestroyed` hook returns an object with two properties:\n\n- `untilDestroyed`: An operator that unsubscribes from the `source` when the component is destroyed.\n\n- `destroyed` - An observable that emits when the component is destroyed.\n\n\n```ts\nimport { interval } from 'rxjs';\nimport { useUntilDestroyed } from '@ngneat/react-rxjs';\n\nfunction CounterComponent() {\n  const { untilDestroyed } = useUntilDestroyed();\n\n  useEffect(() =\u003e {\n    interval(1000).pipe(untilDestroyed()).subscribe(console.log)\n  }, [])\n\n  return ...;\n}\n```\n\n## useEffect$\nThe `useEffect$` hook receives a function that returns an observable, subscribes to it, and unsubscribes when the component destroyed:\n\n```ts\nimport { useEffect$ } from '@ngneat/react-rxjs';\n\nfunction loadTodos() {\n  return fromFetch('todos').pipe(tap({\n    next(todos) {\n      updateStore(todos);\n    }\n  }));\n}\n\nfunction TodosComponent() {\n  const [todos] = useObservable(todos$);\n\n  useEffect$(() =\u003e loadTodos());\n  useEffect$(() =\u003e loadTodos(), deps);\n\n  return \u003c\u003e{todos}\u003c/\u003e;\n}\n```\n## useFromEvent\nIt's the `fromEvent` observable, but with hooks:\n\n```ts\nexport function App() {\n  const [text, setText] = useState('');\n\n  const { ref } = useFromEvent\u003cChangeEvent\u003cHTMLInputElement\u003e\u003e('keyup', (event$) =\u003e\n    event$.pipe(\n      debounceTime(400),\n      distinctUntilChanged(),\n      tap((event) =\u003e setText(event.target.value))\n    )\n  );\n\n  return (\n    \u003c\u003e\n     \u003cinput ref={ref}\u003e\n     { text }\n    \u003c/\u003e\n  )\n```\n\n\n\n\u003cdiv\u003eIcons made by \u003ca href=\"https://www.freepik.com\" title=\"Freepik\"\u003eFreepik\u003c/a\u003e from \u003ca href=\"https://www.flaticon.com/\" title=\"Flaticon\"\u003ewww.flaticon.com\u003c/a\u003e\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngneat%2Freact-rxjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fngneat%2Freact-rxjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngneat%2Freact-rxjs/lists"}