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 🙏

© 2025 – Pkg Stats / Ryan Hefner

usefiltex

v1.2.1

Published

A hook to filter list of objects in React.

Readme

usefiltex

npm

This library is built around two simple pieces: the useFilter() hook and the filter() function.

useFilter() is the core of the library. It lets you declaratively filter an array of objects in React. You provide a list of objects and a list of filters — the hook handles the rest.

The filter() function is a helper to define your filtering rules in a clean and reusable way.

💡 Idea

This library was created to solve a common problem when working with lists in React: filtering objects in a clean, declarative way.

The core concept is to separate the definition of filters from their execution. First, you declare the filters you want to use, then you apply them to your list, and finally you activate them to actually trigger the filtering.

⚡ Apply vs Activate

So, what’s the difference between apply and activate?

  • Apply — tells your code how you want to filter a list. It sets up the filter logic but doesn’t modify the list yet.

  • Activate — actually runs the filtering, applying the active filters to the list.

This approach gives you flexibility: You can apply multiple filters ahead of time and then activate them all at once, or you can apply and activate them one by one, all in a fully declarative and predictable way.

💡 This pattern is super handy when you want your filters to be controlled by UI elements (like checkboxes, dropdowns, or toggles) and avoid hardcoding filter logic directly in your React components.

How to Install

To install usefiltex just use:

npm install usefiltex

Hook API

useFilter()

useFilter({
  list: <list_of_object_to_filter>,
  filters: <list_of_filters>
})

🧾 Arguments

| Name | Description | Required | | --------- | ---------------------------------------------------------- | -------- | | list | The array of objects you want to filter | ✅ Yes | | filters | An array of filters that will be used to filter the list | ✅ Yes |

Example:

useFilter({
  list: [
    { firstName: "John", lastName: "Doe", age: 28 },
    { firstName: "Alice", lastName: "Johnson", age: 22 },
    { firstName: "Bob", lastName: "Brown", age: 17 },
    { firstName: "Charlie", lastName: "Davis", age: 40 }
  ],
  filters: [
    filter("age", (person) => person.age > 25)
  ]
})

NOTE: To declare a filter use the helper function filter() NOTE: The filters do not apply immediately to the given list but we have to apply and activate them with the apply() and activate() methods on the manager.

🔁 Return Values

const { filtered, manager, getFilter } = useFilter(...)

| Name | Description | | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | filtered | The filtered list, in sync with the the all the applied and activated filters. | | manager | An object to manage all the filters: apply them, remove them, toggle, and activate all. | | getFilter | A function to grab filters. You can get filters by name (e.g. getFilter("filterName")) or all the filters by passing "all" to it (e.g. getFilter("all")). |

NOTE: The returned filtered list is exposed under the filtered key by default. This is intended as a placeholder, and it's recommended to rename it to something meaningful for the context, e.g. `const { filtered: filteredBooks } = useFilter(...)

manager API

The manager object handles all interactions with your filters.

It allows you to apply, remove, toggle, reset, and finally activate filters on your list.

🧠 manager Methods

| Method | Description | Returns | | ------------------------------ | -------------------------------------------------------------------------------------------- | --------------------- | | apply(filterName, payload?) | Marks a filter as active and stores an optional payload. | manager (chainable) | | remove(filterName, payload?) | Deactivates the specified filter and stores an optional payload. | manager (chainable) | | toggle(filterName, payload?) | Toggles the active state of a filter. If it was active, it becomes inactive, and vice-versa. | manager (chainable) | | reset() | Deactivates all filters and clears their active state. | manager (chainable) | | activate() | Applies all active filters to the list and updates the filtered result. | void |

⚠️ Notes

apply(), remove(), toggle() and reset() do not immediately filter the list — they only update the filter state.

You must call activate() to apply the current active filters and update the filtered result.

All methods (except activate()) return the manager itself, so you can chain calls.

filter() Function

The filter() function is used to define filtering rules for useFilter(). It returns a filter object containing:

|Property|Description| |---|---| |name|The identifier of the filter. Used to reference the filter when applying, removing or toggling it.| |filter|A callback function that defines the filtering logic. It receives the current list item (and optionally a payload if passed) and must return true to include the item in the filtered list.|

Example

const myFilter = filter("minAge", (person, minAge) => person.age >= minAge);

In this example:

  • name is "minAge".
  • The filtering logic keeps only the people whose age is greater than or equal to minAge.
  • payload is expected to be a number (minAge) when applying the filter.

Examples - Filtering Books

For the following examples we'll use a list of books:

const books = [
  { title: "Harry Potter and the Sorcerer's Stone", author: "J.K. Rowling", genre: "Fantasy", year: 1997 },
  { title: "The Hobbit", author: "J.R.R. Tolkien", genre: "Fantasy", year: 1937 },
  { title: "1984", author: "George Orwell", genre: "Dystopian", year: 1949 },
  { title: "To Kill a Mockingbird", author: "Harper Lee", genre: "Classic", year: 1960 },
  { title: "Sapiens", author: "Yuval Noah Harari", genre: "Non-fiction", year: 2011 }
];

Let's create also a component to display the list of books:

function FilteredBooks({ books }) {
  return (
    <div>
      {books.map((book) => (
        <div key={book.title}>
          <h2>{book.title} - {book.year}</h2>
          <p>{book.author}</p>
          <p>{book.genre}</p>
        </div>
      ))}
    </div>
  )  
}

Single Filter

Let's imagine we want to obtain all the books published after the year 2000:

import { useFilter, filter } from 'usefiltex';

function Books() {

  const { filtered: filteredBooks, manager } = useFilter({
    // list to filter
    list: books,
    filters: [
      // declare our filters
      filter("year", (book) => book.year > 2000)
    ]
  })
  
  const filter = () => {
    manager
      .apply("year")  // apply the 'year' filter
      .activate()     // activate all the applied filters
  }

  return (
    <div>
      <FilteredBooks books={filteredBooks}>
      <button onClick={filter}>Filter</button>
    </div>
  )
}

When the user clicks on the Filter button, the declared "year" filter will be applied and immediately activated, showing only Sapiens - by Yuval Noah Harari.

NOTE: Use function expressions with const instead of using function declarations with the function keyword.

Multiple Filters

Let's imagine we want to obtain all the fantasy books published after the year 1990:

import { useFilter, filter } from 'usefiltex';

function Books() {

  const { filtered: filteredBooks, manager } = useFilter({
    // list to filter
    list: books,
    filters: [
      // declare our filters
      filter("fantasy", (book) => book.genre === "Fantasy"),
      filter("year", (book) => book.year > 1990),
    ]
  })
  
  const filter = () => {
    manager
      .apply("fantasy") // apply the 'fantasy' filter
      .apply("year")    // apply the 'year' filter
      .activate()       // activate all the applied filters
  }

  return (
    <div>
      <FilteredBooks books={filteredBooks}>
      <button onClick={filter}>Filter</button>
    </div>
  )
}

Apply Before and Activate After

Let's imagine we want our user to be able to apply different filters depending on its needs and activate all of them all at once:

import { useFilter, filter } from 'usefiltex';

function Books() {

  const { filtered: filteredBooks, manager } = useFilter({
    // list to filter
    list: books,
    filters: [
      // declare our filters
      filter("fantasy", (book) => book.genre === "Fantasy"),
      filter("year", (book) => book.year > 1990),
    ]
  })
  
  const applyFantasyFilter = () => {
    manager.apply("fantasy") // apply the 'fantasy' filter
  }

  const applyYearFilter = () => {
    manager.apply("year") // apply the 'year' filter
  }
  
  const activateFilter = () => {
    manager
      .activate() // activte all the applied filters
  }

  return (
    <div>
      <FilteredBooks books={filteredBooks}>
      <button onClick={applyFantasyFilter}>Fantasy</button>
      <button onClick={applyYearFilter}>Year</button>
      <button onClick={activateFilter}>Filter</button>
    </div>
  )
}

Applied Filters Feedback

If we want to let our user to know which filters are applied whenever they want, we can use the returned getFilter() function returned by useFilter().

In this way the user can use the status of the filter to toggle the style of a button:

import { useFilter, filter } from 'usefiltex';

function Books() {

  const {
    filtered: filteredBooks,
    manager,
    getFilter
  } = useFilter({
    // list to filter
    list: books,
    filters: [
      // declare our filters
      filter("fantasy", (book) => book.genre === "Fantasy"),
    ]
  })
  
  const applyFilter = () => {
    manager.
      toggle("Fantasy") // toggle filter
  }
  
  const filter = () => {
    manager
      .activate() // activte all the applied filters
  }
  
  return (
    <div>
      <FilteredBooks books={filteredBooks}>
      <button
        style={getFilter("fantasy").isActive ? { background: "blue"} : {}}
        onClick={applyFilter}
      >Filter</button>
      <button onClick={filter}>Filter</button>
    </div>
  )
}

Dynamic Filters

In this example, we’ll use payload to pass dynamic filter conditions — like filtering books by publication year range.

This shows how flexible your hook is when the filtering rules depend on user input (search bars, sliders, dropdowns, etc.).

import { useFilter, filter } from 'usefiltex';

function Books() {
  const { filtered: filteredBooks, manager } = useFilter({
    list: books,
    filters: [
        filter("yearRange", (book, [minYear, maxYear]) => book.year >= minYear && book.year <= maxYear),
        filter("byAuthor", (book, searchTerm) => 
        book.author.toLowerCase().includes(searchTerm.toLowerCase())
      )
    ]
  });
  
  const filterByAuthor = () => {
    manager
      .apply("byAuthor", "Kyle")  // search for "Kyle" in the author name
  }
  
  const filterByYear = () => {
    manager
      .apply("yearRange", [2010, 2020])    // Year between 2010 and 2020
  }
  
  const filter = () => {
    manager
      .activate();
  }
  
  return (
    <div>
      <FilteredBooks books={filteredBooks}>
      <button onClick={filterByAuthor}>Author Filter</button>
      <button onClick={filterByYear}>Year Filter</button>
      <button onClick={filter}>Filter</button>
    </div>
  )
}

💬 Feedback

If you find a bug, have an idea for a feature, or just want to say hi — open an issue!
I'd love to hear how you're using this library and how it can improve.


Thanks for checking out usefiltex!

HAPPY FILTERING! 🚀