1.0.5 • Published 6 months ago

react-api-search v1.0.5

Weekly downloads
-
License
ISC
Repository
github
Last release
6 months ago

React API Search

A highly customizable, debounce-enabled, and fully-featured React API Search component designed to fetch and display search results asynchronously. Ideal for scenarios where the search query is used to fetch data from APIs or databases, with built-in support for loading, error handling, and no-result states.

Features

  • Debounced Search: Customizable debounce delay to prevent excessive API calls while typing.
  • Loading & Error States: Display loading spinners or error messages while fetching data.
  • Dropdown Menu: A dropdown menu that displays search results, with full control over its visibility.
  • Customizable Styles: Easily apply custom styles to the container, input field, results list, items, and icons.
  • Flexible Data Fetching: Works with any asynchronous data-fetching method.
  • TypeScript Support: Fully typed for better development experience and safety.

Installation

npm install react-api-search

or

yarn add react-api-search

Usage

import SearchBar from 'react-api-search';

type Post = {
  id: number;
  title: string;
  body: string;
};

const fetchPosts = async (query: string): Promise<Post[]> => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/posts?q=${encodeURIComponent(query)}`
  );
  if (!response.ok) throw new Error('Failed to fetch posts');
  const data = await response.json();
  return data;
};

function App() {
  return (
    <div style={{ padding: '20px' }}>
      <h1>Posts Search</h1>
      <div style={{ width: '40rem' }}>
        <SearchBar<Post>
          placeholder='Search for posts...'
          fetchData={fetchPosts}
          loadingElement={
            <div className='custom-loading'>Please wait, fetching data...</div>
          }
          emptyElement={
            <div>No posts match your search. Try something else!</div>
          }
          errorElement={
            <div>Oops, something went wrong. Please try again later.</div>
          }
          renderItem={(post) => (
            <div
              style={{ padding: '10px', borderBottom: '1px solid #ccc' }}
              onMouseEnter={(e) => {
                e.currentTarget.style.backgroundColor = '#f0f0f0'; // hover background
              }}
              onMouseLeave={(e) => {
                e.currentTarget.style.backgroundColor = 'transparent'; // reset background
              }}
            >
              <h3 style={{ margin: 0 }}>{post.title}</h3>
              <p style={{ margin: '5px 0', fontSize: '0.9em', color: '#555' }}>
                {post.body}
              </p>
            </div>
          )}
          onSelect={(post) => alert(`Selected post: ${post.title}`)}
          debounceDelay={500}
        />
      </div>
    </div>
  );
}

export default App;

Props

PropTypeDescriptionDefault Value
placeholderstringPlaceholder text for the input field.'Search...'
fetchData(query: string) => Promise<T[]>A function that fetches data based on the search query.N/A
renderItem(item: T) => JSX.ElementA function to render each search result item.N/A
onSelect(item: T) => voidA callback function triggered when a user selects an item.undefined
loadingElementJSX.ElementJSX to display while results are loading.<div>Loading...</div>
emptyElementJSX.ElementJSX to display when no results are found.<div>No results found</div>
errorElementJSX.ElementJSX to display when an error occurs.<div>Something went wrong</div>
debounceDelaynumberThe debounce delay in milliseconds.500
containerClassNamestringCustom class for the search bar container.undefined
inputClassNamestringCustom class for the input field.undefined
dropdownClassNamestringCustom class for the dropdown containing search results.undefined
itemClassNamestringCustom class for each search result item.undefined
hideSearchIconbooleanWhether to hide the search icon.false
searchIconClassNamestringCustom class for the search icon.undefined
closeIconClassNamestringCustom class for the close icon.undefined
inputFontColorstringFont color of the input field.#000
inputBorderRadiusstringBorder radius of the input field.'8px'
inputBorderColorstringBorder color of the input field.#ccc
inputFontSizestringFont size of the input field.'16px'
inputHeightstringHeight of the input field.'45px'
inputBackgroundColorstringBackground color of the input field.#fff
searchIconColorstringColor of the search icon.#888
closeIconColorstringColor of the close icon.#888
dropDownBackgroundColorstringBackground color of the dropdown.#fff
dropDownBorderColorstringBorder color of the dropdown.#ccc
dropDownMaxHeightstringMaximum height of the dropdown.'60vh'
dropDownBorderRadiusstringBorder radius of the dropdown.'8px'
scrollBarColorstringColor of the scrollbar inside the dropdown.#ccc

License

This project is licensed under the MIT License. See the LICENSE file for more information.

Contributing

Contributions are welcome! 🎉

  1. Fork the project.
  2. Create a feature branch (git checkout -b feature-name).
  3. Commit your changes (git commit -m 'Add some feature').
  4. Push to the branch (git push origin feature-name).
  5. Open a Pull Request.

For more information, please checkout the CONTRIBUTIONS document.


Note: This component uses TypeScript and provides full type safety. It can be easily integrated into any TypeScript or JavaScript-based React project.

1.0.5

6 months ago

1.0.4

7 months ago

1.0.3

7 months ago

1.0.2

7 months ago

1.0.1

7 months ago

1.0.0

7 months ago