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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@browser-search/react-browser-search

v1.0.0

Published

React hooks for browser-search library

Readme

react-browser-search

-> Take a look at the demo

This library provides react hooks to the browser-search library Please read the documentation of browser-search before using

Get Started

Installation

Yarn

yarn add @browser-search/browser-search
yarn add @browser-search/react-browser-search

Npm

npm install -S @browser-search/browser-search
npm install -S @browser-search/react-browser-search

Usage flow

graph LR
0[Wrap components with provider]--> A
A[Create  document store]--> B[Add Documents]
B --> C[Run  a query]
B --> E[etc.]

Step 1 - Wrap your component tree in the react-browser-search provider

For the hooks to work, you need to wrap your component tree in the provider which contains a client + cache layer. See BrowserSearchProvider for usage

Step 2 - Create a store

To get started, create a store that will later hold your data. You need to know in advance

  • the type of the documents you will store
  • the fields that you will use for filtering / sorting. Those fields must be indexed. See useCreateStore

Step 3 - Add documents

Then you can add documents to the newly created store See useAddDocumentsToStore

Step 4 - run a search query

You can now run complex queries to filter and sort your document, and display them to your users. See useQuery for usage

API Methods

useCreateStore

see createStore

Signature

<TDocument>(): [(request: CreateStoreRequest<TDocument>) =>  Promise<void>, QueryState<TDocument>]

Generics

  • TDocument is the type of the document you will store

Parameters

none

Return value

[(request: CreateStoreRequest<TDocument>) =>  Promise<void>, QueryState<TDocument>]

With

  • request: CreateStoreRequest<TDocument> is the object containing the request for the store creation
    • storeId: string the name of the store to create
    • indexConfig: SimplifiedIndexConfig<DataSchema> the fields to index. see reference here
    • keyPath: keyof TDocument is the field which is be the primary key. That field does not need to be included in the indexConfig above
  • queryState: UseCreateStoreQueryState: see QueryState

Example

Let's say we want to store books of the following type:

export  interface  Book {
	isbn: string; // primary key
	title: string;
	releaseDate: string;
	authors: string[];
	categories: Array<'fantasy' | 'sci-fi' | 'thriller'>;
	description: string;
}

We want to be able to filter and sort on every field but the description.

import { SimplifiedIndexConfig } from '@browser-search/browser-search';
import { useCreateStore, UseCreateStoreQueryState } from  '@browser-search/react-browser-search';

const storeName = "bookLibrary";
const indexConfig: SimplifiedIndexConfig<Book> = {
	simple: ['title', 'releaseDate'],
	array: ['authors', 'categories'],
};
const keyPath = 'isbn';

const  useCreateLibraryStore = (): [() =>  Promise<void>, UseCreateStoreQueryState<Book>] => {

	const [createStore, createStoreQueryState] = useCreateStore<Book>();
	const  createLibraryStore = () =>  createStore({
	  storeId,
	  indexConfig,
	  keyPath,
	});

	return [createPersonStore, createStoreQueryState];
};

useAddDocumentsToStore

see addDocumentsToStore

Signature

<TDocument>(): [(request: AddDocumentsToStoreRequest<TDocument>) =>  Promise<void>, QueryState<TDocument>]

Generics

  • TDocument is the type of the document you will store

Parameters

none

Return value

[(request: AddDocumentsToStoreRequest<TDocument>) =>  Promise<void>, QueryState<TDocument>]

With

  • request: AddDocumentsToStoreRequest<TDocument> is the object containing the request to add the data to the store
    • storeId: string the name of the store to create
    • documents: TDocument[] is the array of documents to be stored
  • queryState: UseAddDocumentsToStoreQueryState: see QueryState

Example

import { useAddDocumentsToStore, UseAddDocumentsToStoreQueryState } from  '@browser-search/react-browser-search';

const storeId = 'bookLibrary';

const useAddBooksToLibraryStore = (): [(books: Book[]) =>  Promise<void>, UseAddDocumentsToStoreQueryState<Book>] => {
	const [addDocumentsToStore, addDocumentsToStoreQueryState] = useAddDocumentsToStore<Person>();

	const addBooksToLibraryStore = (books: Book[]) => {
		return addDataToStore({
			storeId,
			documents: books
		})
	}

	return [addBooksToLibraryStore, addDocumentsToStoreQueryState];
}

useQuery

see queryStore

Hook behaviour:

  • Every query response is cached
  • The cache is automatically invalidated at any store mutation and the request is automatically re-triggered
  • A request automatically cancels a previously pending request

Signature

<TDocument, TFilterId  extends  string = string>(request: QueryRequest<TDocument, TFilterId>): QueryState<TDocument, TFilterId>

Generics

  • TDocument is the type of the document you will store
  • TFilterId is the string union of all the filters ids defined in the filterConfiguration object, passed in the request. Defaults to a string.

Parameters

  • request: QueryRequest<TDocument, TFilterId> is the object containing the query parameters. Refer to QueryRequest

Return value

UseQueryQueryState<TDocument, TFilterId>

see QueryState

Example

import { useQuery, UseQueryQueryState } from  '@browser-search/react-browser-search';
import { QueryRequest, FilterConfig } from  '@browser-search/browser-search';

type  FilterIds = 'categoryFantasy' | 'categorySciFi' | 'categoryThriller';
const storeId = 'bookLibrary';


export  const  useBookQuery = (filterApplied: FilterIds[]): UseQueryQueryState<Book, FilterId> => {
	const filterConfig: FilterConfig<Book, FilterIds> = 
	[
		[
			{ id:  'categoryFantasy', field: 'categories', operator: 'contains', operand:  'fantasy' },
			{ id:  'categorySciFi', field: 'categories', operator: 'contains', operand: 'sci-fi' },
			{ id:  'categoryThriller', field: 'categories', operator: 'contains', operand:  'thriller' },
		],
	];
	
	const  queryRequest: QueryRequest<Person, FilterId> = () => (
		storeId,
		filterConfig,
		filtersApplied, // the ids of the filter in the filter configuration that you are filtering on. Example: ['categoryFantasy', 'categorySciFi']
		orderBy:  'releaseDate',
		orderDirection: 'DESC',
		perPage:  10,
		page:  0,
	};

	return  useQuery<Book, FilterId>(queryRequest);
}

useIndexValues

see getIndexValues

Hook behaviour:

  • Every query response is cached.
  • The cache is automatically invalidated on any store mutation and the request is automatically re-triggered

Signature

<T  extends  IDBValidKey>({storeId, field}: GetIndexValuesRequest): QueryState<T>

Generics

  • T is the type of the property indexed, that should be compliant with the IDBValidKey interface, where IDBValidKey = number | string | Date | BufferSource | IDBValidKey[]

Parameters

  • request: GetIndexValuesRequest is the object containing the request parameters.
    • storeId: string: the store name
    • field: string is the property for which you want to get all the values. It should be indexed at the store creation. See SimplifiedIndexConfig reference

Return value

UseIndexValuesQueryState<T>

see QueryState

Example

import { useIndexValues, UseIndexValuesQueryState } from  '@browser-search/react-browser-search';

const storeId = 'bookLibrary';

// to get the list of all the titles stored
export const  useBookTitleValues = (): UseIndexValuesQueryState<string> => {
	return  useIndexValues<string>({
		storedId,
		field: 'title',
	});
}

useDeleteStore

see deleteStore

Signature

(): [(request: DeleteStoreRequest) =>  Promise<void>, QueryState]

Parameters

none

Return value

[(request: DeleteStoreRequest) =>  Promise<void>, QueryState]

With

  • request: DeleteStoreRequest is the object containing the request for the store deletion
    • storeId: string the name of the store to create
  • queryState: UseDeleteStoreQueryState: see QueryState

Example

import { useDeleteStore, UseDeleteStoreQueryState } from  '@browser-search/react-browser-search';

const  useDeleteLibraryStore = (): [() =>  Promise<void>, UseDeleteStoreQueryState] => {

	const [deleteStore, deleteStoreQueryState] = useDeleteStore();
	const  deleteLibraryStore = () =>  deleteStore({
	  storeId: "bookLibrary",
	});

	return [deleteLibraryStore, deleteStoreQueryState];
};

BrowserSearchProvider

This react component connects your tree to the browser-search context

  • any component calling a browser-search hook should be a child of this one

Example

import { BrowserSearchProvider } from  '@browser-search/react-browser-search';


<BrowserSearchProvider>
	<App />
</BrowserSearchProvider>

API Interfaces

QueryState

This interface is returned by every hook. It is a react-state (meaning your component will re-render each time the query state changes) that represents the progress of the request.

QueryState is a union type that can take the following shape:

IdleQueryState | LoadingQueryState | SuccessQueryState | StaleQueryState | ErrorQueryState
  • IdleQueryState: when the request is not started. Example: a store mutation not yet called.
  • LoadingQueryState: when the request is ongoing. React-state equivalent of a pending promise.
  • SuccessQueryState: when the request has succeeded. React-state equivalent of a resolved promise.
  • StaleQueryState: when a new request is loading after a previous one succeeded. Only returned for non-mutation hooks, ie. only for useIndexValues and useQuery. This state is useful when you still need access to the stale data while the new request is loading.
  • ErrorQueryState: when the request failed. React-state equivalent of a rejected promise.
graph LR
0[IdleQueryState]-->A
A[LoadingQueryState]--> B[SuccessQueryState]
A --> C[ErrorQueryState]
B --> D[StaleQueryState]
D --> B
D --> C

Definition

interface  IdleQueryState {
	status: 'idle';
	isFetching: false;
}

interface  LoadingQueryState<Request> {
	status: 'loading';
	request: Request;
	isFetching: true;
}

interface  SuccessQueryState<Request, Response> {
	status: 'success';
	request: Request;
	response: Response;
	isFetching: false;
}

interface  StaleQueryState<Request, Response> {
	status: 'stale';
	request: Request;
	response: Response;
	newRequest: Request;
	isFetching: true;
}

interface  ErrorQueryState<Request, Error> 
	status: 'error';
	request: Request;
	error: Error;
	isFetching: false;
}

type  QueryState<Request, Response, Error> = IdleQueryState | LoadingQueryState<Request> | SuccessQueryState<Request, Response> | StaleQueryState<Request, Response> | ErrorQueryState<Request, Error>;