{"id":17089823,"url":"https://github.com/magellol/reactive-search","last_synced_at":"2025-04-12T22:13:57.542Z","repository":{"id":57348215,"uuid":"82193204","full_name":"Magellol/reactive-search","owner":"Magellol","description":"Incremental search using React and RxJS","archived":false,"fork":false,"pushed_at":"2017-03-14T16:10:13.000Z","size":61,"stargazers_count":15,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-12T00:33:07.388Z","etag":null,"topics":["component","field","incremental","react","reactive","rxjs","search"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/Magellol.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-02-16T15:08:25.000Z","updated_at":"2018-06-29T09:54:48.000Z","dependencies_parsed_at":"2022-08-31T17:51:08.627Z","dependency_job_id":null,"html_url":"https://github.com/Magellol/reactive-search","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Magellol%2Freactive-search","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Magellol%2Freactive-search/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Magellol%2Freactive-search/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Magellol%2Freactive-search/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Magellol","download_url":"https://codeload.github.com/Magellol/reactive-search/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248637789,"owners_count":21137538,"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":["component","field","incremental","react","reactive","rxjs","search"],"created_at":"2024-10-14T13:49:20.915Z","updated_at":"2025-04-12T22:13:57.519Z","avatar_url":"https://github.com/Magellol.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/Magellol/reactive-search.svg?branch=master)](https://travis-ci.org/Magellol/reactive-search)\n\n# Reactive search\nReact component allowing you to query some api \"as-you-type\".\nOut of the box, it takes care of debouncing input events for you, so you don't over query your api.\n\n## Table of Contents\n- [Demo](#demo)\n- [Installation](#installation)\n- [Quickstart](#quickstart)\n- [Configure](#configure)\n- [Contribute](#contribute)\n- [Disclaimer](#disclaimer)\n- [License](#license)\n\n## Demo\n[Check out the demo](http://twobugsonecommit.com/).\n_Please keep in mind that the component doesn't do any caching whatsoever, everything is up to you. In this demo, I've implemented a really basic redis caching to speed things up._\n\n## Installation\n```javascript\nyarn add reactive-search\n\n// Or via npm\nnpm i --save reactive-search\n```\n\n## Quickstart\nHere's a quick example of what it would look like if you were to use the component.\n\n```javascript\nimport ReactiveSearch from 'reactive-search';\n\nexport default function App() {\n  return (\n    \u003cReactiveSearch\n      classes={['input', 'rounded-corner']}\n      getUrlToRequest={searchTerm =\u003e `/search/${searchTerm}`}\n      onResponse={response =\u003e console.log('Got response', response)}\n      shouldRetryOnError={error =\u003e false}\n      onFatalError={error =\u003e console.error('Big Bad Bug', error)}\n    /\u003e\n  );\n}\n```\n\n## Configure\nThe component offers a few props (some required) to allow you to customized some behaviours.\n\n### `classes`\n\n| **Accepted Types:** | **Default Value** |   **Required**    |\n|---------------------|-------------------|-------------------|\n|  `Array` | `[]` | `false` |\n\nThe `classes` prop takes an array of strings and will join them to build the `className` string.\n```javascript\n// Produces `className=\"input rounded-corner\"`\n\u003cReactiveSearch classes={['input', 'rounded-corner']} /\u003e\n```\n\n### `getUrlToRequest`\n\n| **Accepted Types:** | **Default Value** |   **Required**    |\n|---------------------|-------------------|-------------------|\n|  `Function` | `None` | `true`  |\n\n`getUrlToRequest` is a function that'll be called whenever an API call is about to be made.\nYour callback will receive the search term (after any filtering the component does).\n\n```javascript\nfunction buildUrl(searchTerm) {\n  return `http://fastest-api-in-the-world.com/search?s=${searchTerm}`;\n}\n\n\u003cReactiveSearch getUrlToRequest={buildUrl} /\u003e\n```\n\n**Note:** Your function _will not_ be called if the value has been filtered out.\nReactiveSearch trims and removes extraneous spaces before letting the input going through.\nIf the output results in empty string, your callback will not be called.\n\nHere's what it does under the hood:\n```javascript\nthis.input$\n  .map(value =\u003e value.trim().toLowerCase().replace(/\\s\\s+/g, ' '))\n  .filter(value =\u003e value.length) // Will not let through empty strings\n  ...\n  .switchMap((searchTerm) =\u003e {\n    const url = getUrlToRequest(searchTerm);\n    ...\n  });\n```\n\n### `onResponse`\n\n| **Accepted Types:** | **Default Value** |   **Required**    |\n|---------------------|-------------------|-------------------|\n|  `Function` | `None` | `true`  |\n\n`onResponse` is a callback that'll be called whenever the API sent back a response. It'll receive whatever your `fetch`\nimplementation returns from that call. Please keep in mind that this component uses by default the native fetch browser implementation. So still by default, a response with a **status that is not 200** is still considered successful by the native `fetch` spec. This behaviour may differ if you're using a custom polyfill.\n\n```javascript\nfunction handleResponse(response) {\n  response.json().then((content) =\u003e {\n    this.setState({ content });\n  });\n}\n\n\u003cReactiveSearch onResponse={handleResponse} /\u003e\n```\n\n### `shouldRetryOnError`\n\n| **Accepted Types:** | **Default Value** |   **Required**    |\n|---------------------|-------------------|-------------------|\n|  `Function` | `() =\u003e false` | `false`  |\n\nOptional function you can pass to evaluate if an error you encountered somewhere in the pipeline of doing a request should be ignored. If your function returns `true`, the error is ignored and we subscribe again to events. If your function returns `false`, `onFatalError` will be called and no more further events will be dispatched.\n\n```javascript\nfunction shouldRetryOnError(error) {\n  return error.status \u003c 500;\n}\n\n\u003cReactiveSearch shouldRetryOnError={shouldRetryOnError} /\u003e\n```\n\n_The reason this exists is because this component uses the [RxJS](http://reactivex.io/rxjs/) library and by default when an observable receives an error, it will unsubscribe and will not receive any further events. Think of `shouldRetryOnError` as a retry behaviour._\n\n### `onFatalError`\n\n| **Accepted Types:** | **Default Value** |   **Required**    |\n|---------------------|-------------------|-------------------|\n|  `Function` | `None` | `true`  |\n\n`onFatalError` is the final callback that will be called when an unhandled error bubbles up. After this callback has been called, no more events will be dispatched and no more API requests will be made. You should use this to produce any warning for you and your users.\n\n```javascript\nfunction fatalErrorHandler(error) {\n  showErrorMessageToUser(error.message);\n  log(error);\n}\n\n\u003cReactiveSearch onFatalError={fatalErrorHandler} /\u003e\n```\n\n## Disclaimer\n- It's a BYOP (bring your own Promise) and BYOF (bring your own fetch) library.\n- This component doesn't perform any caching whatsoever. Client side/server side caching should be your responsibility.\n\n## Contribute\nContributions are welcome! Please open issues when you found a bug.\nIf you wish to fix a bug, a pull request is necessary. The PR is required to pass the tests and the linter before being merged.\nIf you wish to work on a new feature, open an issue and we'll talk about it.\n\n```bash\n# Run the test\n- yarn run test\n\n# Run the linter\n- yarn run lint\n\n# Watch changes\n- yarn run watch\n```\n\n## License\n[MIT](LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagellol%2Freactive-search","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagellol%2Freactive-search","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagellol%2Freactive-search/lists"}