npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

reactive-search

v0.0.3

Published

Incremental search using React and Rxjs

Downloads

18

Readme

Build Status

Reactive search

React component allowing you to query some api "as-you-type". Out of the box, it takes care of debouncing input events for you, so you don't over query your api.

Table of Contents

Demo

I'm working on a demo, hopefully it'll be available soon enough.

Installation

yarn add reactive-search

// Or via npm
npm i --save reactive-search

Quickstart

Here's a quick example of what it would look like if you were to use the component.

import ReactiveSearch from 'reactive-search';

export default function App() {
  return (
    <ReactiveSearch
      classes={['input', 'rounded-corner']}
      getUrlToRequest={searchTerm => `/search/${searchTerm}`}
      onResponse={response => console.log('Got response', response)}
      shouldRetryOnError={error => false}
      onFatalError={error => console.error('Big Bad Bug', error)}
    />
  );
}

Configure

The component offers a few props (some required) to allow you to customized some behaviours.

classes

| Accepted Types: | Default Value | Required | |---------------------|-------------------|-------------------| | Array | [] | false |

The classes prop takes an array of strings and will join them to build the className string.

// Produces `className="input rounded-corner"`
<ReactiveSearch classes={['input', 'rounded-corner']} />

getUrlToRequest

| Accepted Types: | Default Value | Required | |---------------------|-------------------|-------------------| | Function | None | true |

getUrlToRequest is a function that'll be called whenever an API call is about to be made. Your callback will receive the search term (after any filtering the component does).

function buildUrl(searchTerm) {
  return `http://fastest-api-in-the-world.com/search?s=${searchTerm}`;
}

<ReactiveSearch getUrlToRequest={buildUrl} />

Note: Your function will not be called if the value has been filtered out. ReactiveSearch trims and removes extraneous spaces before letting the input going through. If the output results in empty string, your callback will not be called.

Here's what it does under the hood:

this.input$
  .map(value => value.trim().toLowerCase().replace(/\s\s+/g, ' '))
  .filter(value => value.length) // Will not let through empty strings
  ...
  .switchMap((searchTerm) => {
    const url = getUrlToRequest(searchTerm);
    ...
  });

onResponse

| Accepted Types: | Default Value | Required | |---------------------|-------------------|-------------------| | Function | None | true |

onResponse is a callback that'll be called whenever the API sent back a response. It'll receive whatever your fetch implementation 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.

function handleResponse(response) {
  response.json().then((content) => {
    this.setState({ content });
  });
}

<ReactiveSearch onResponse={handleResponse} />

shouldRetryOnError

| Accepted Types: | Default Value | Required | |---------------------|-------------------|-------------------| | Function | () => false | false |

Optional 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.

function shouldRetryOnError(error) {
  return error.status < 500;
}

<ReactiveSearch shouldRetryOnError={shouldRetryOnError} />

The reason this exists is because this component uses the 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.

onFatalError

| Accepted Types: | Default Value | Required | |---------------------|-------------------|-------------------| | Function | None | true |

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.

function fatalErrorHandler(error) {
  showErrorMessageToUser(error.message);
  log(error);
}

<ReactiveSearch onFatalError={fatalErrorHandler} />

Disclaimer

  • It's a BYOP (bring your own Promise) and BYOF (bring your own fetch) library.
  • This component doesn't perform any caching whatsoever. Client side/server side caching should be your responsibility.

Contribute

Contributions are welcome! Please open issues when you found a bug. If 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. If you wish to work on a new feature, open an issue and we'll talk about it.

# Run the test
- yarn run test

# Run the linter
- yarn run lint

# Watch changes
- yarn run watch

License

MIT