npm package: @osama-yousuf/react-infinite-scroll-hook
Description: A powerful, production-ready **React Infinite Scroll Hook** with:
Latest version: 0.1.9

# @osama-yousuf/react-infinite-scroll-hook

A powerful, production-ready **React Infinite Scroll Hook** with:

✅ Axios support  
✅ Token / Bearer authentication  
✅ Custom API routes  
✅ GET / POST / PUT / DELETE  
✅ Params OR Body pagination  
✅ AbortController handling  
✅ Works with any API response shape  
✅ Fully TypeScript typed (IDE suggestions enabled)  
✅ IntersectionObserver based infinite loading  

---

## 📦 Installation

```bash
npm install @osama-yousuf/react-infinite-scroll-hook axios react
```

If you're using TypeScript, also install:

```bash
npm install -D typescript @types/react
```

---

## ✅ Basic Usage (GET API)

```jsx
import { useInfiniteScroll } from "@osama-yousuf/react-infinite-scroll-hook";

const App = () => {
  const { data, lastElementRef, loading } = useInfiniteScroll({
    url: "https://api.example.com/users",
    method: "GET",
    params: { status: "active" },
    accessorKey: "data.data",
  });

  return (
    <>
      {data.map((item, index) => (
        <div
          key={item.id}
          ref={data.length === index + 1 ? lastElementRef : null}
        >
          {item.name}
        </div>
      ))}

      {loading && <p>Loading...</p>}
    </>
  );
};
```

---

## ✅ POST API With Body + Token

```jsx
const { data, refresh } = useInfiniteScroll({
  url: "https://api.example.com/orders",
  method: "POST",
  body: {
    startDate: "2024-01-01",
    endDate: "2025-01-01",
  },
  token: "YOUR_BEARER_TOKEN",
  accessorKey: "data.data",
});
```

---

## ✅ With Custom Axios Instance

```js
import axios from "axios";

const apiInstance = axios.create({
  baseURL: "https://api.example.com",
});
```

```jsx
useInfiniteScroll({
  url: "/orders",
  instance: apiInstance,
  method: "POST",
});
```

---

## ✅ With Search + Filters

```jsx
const params = {
  query: searchValue,
  status: selectedStatus,
};

useInfiniteScroll({
  url: "/users",
  params,
});
```

## ✅ With Search + Filters
```jsx
useInfiniteScroll({
  url: "/orders",
  method: "POST",
  body: { limit: 10 },
  pageInParams: false,
  pageKey: "page",
  accessorKey: "data.data",
});
```
---

## ✅ Hook Options

| Option       | Type                           | Default    | Description               |
| ------------ | ------------------------------ | ---------- | ------------------------- |
| url          | `string`                       | required   | API endpoint              |
| method       | `GET \| POST \| PUT \| DELETE` | `GET`      | HTTP method               |
| params       | `object`                       | `{}`       | Query parameters          |
| body         | `object`                       | `{}`       | Request body              |
| token        | `string`                       | optional   | Bearer token              |
| instance     | `AxiosInstance`                | `axios`    | Custom axios instance     |
| accessorKey  | `string \| function`           | `"data"`   | Path to response data     |
| pageInParams | `boolean`                      | `true`     | Send pagination in params |
| pageKey      | `string`                       | `"pageNo"` | Pagination key name       |

---

## ✅ Returned Values

```ts
{
  data,
  lastElementRef,
  loading,
  hasMore,
  refresh
}
```

| Key            | Description            |
| -------------- | ---------------------- |
| data           | Loaded items           |
| lastElementRef | Attach to last element |
| loading        | API loading state      |
| hasMore        | Indicates more data    |
| refresh        | Manually reload        |

---

## ✅ Pagination Key Support

Default pagination key is pageNo.
If your API uses a different key:
```js
useInfiniteScroll({
  url: "/users",
  params: {},
  pageKey: "page",
});
```

---

## ✅ Manual Refresh

```jsx
<button onClick={refresh}>Refresh</button>
```

---

## ✅ Debounced Search Example

```js
const [search, setSearch] = useState("");
const [debouncedSearch, setDebouncedSearch] = useState("");

useEffect(() => {
  const timer = setTimeout(() => setDebouncedSearch(search), 500);
  return () => clearTimeout(timer);
}, [search]);
```

---

## ✅ Abort Controller Auto Handling

Previous API requests are automatically cancelled when new API is triggered.

---

## ✅ TypeScript Support

Fully typed for:

✅ Axios Instance
✅ Props
✅ API response
✅ State
✅ IDE auto‑suggestions

---

## ✅ Example API Response

```json
{
  "data": {
    "data": [
      { "id": 1, "name": "John" }
    ]
  }
}
```

Accessor used:

```js
accessorKey: "data.data"
```

---

## 🧠 Best Practices

✔ Always debounce search inputs
✔ Always use `accessorKey`
✔ Use `instance` for large apps
✔ Use `token` for secured APIs

---

## 🧑‍💻 Author

**Osama Yousuf**
GitHub: [https://github.com/osamayousuf90](https://github.com/osamayousuf90)

---

## ⭐ Support

If you like this package:

✅ Star it on GitHub
✅ Share it with devs
✅ Contribute 🔥

---

## 🔍 Keywords

react infinite scroll hook, react infinite scroll, infinite scroll hook, react pagination hook, axios infinite scroll, react data fetching hook, intersection observer, typescript react hook

## 📜 License

MIT License