npm package: @gryfnie/react-asyncify
Description: Say goodbye to messy async code! react-asyncify makes handling asynchronous operations in React a breeze. Whether you’re loading data, dealing with errors, or just want to keep your UI smooth and responsive, this simple, reusable polymorphic component has
Author: Michał Porydzaj
Latest version: 1.0.1

# 🔄 @gryfnie/react-asyncify

Say goodbye to messy async code! `@gryfnie/react-asyncify` makes handling asynchronous operations in React a breeze. Whether you’re loading data, dealing with errors, or just want to keep your UI smooth, this simple, reusable polymorphic component has you covered.

## Features
- 🔄 **Polymorphic**: Render as any HTML element or custom component
- 💻 Enhances developer experience with clean, maintainable code
- 🚀 Simplifies asynchronous operations in React
- 🔄 Handles loading, success, and error states seamlessly
- ⚙️ Provides hooks for custom logic with `onResolve` and `onReject`
- 🎨 Fully customizable and easy to integrate
- ♻️ Reusable across different components and projects
- 🧩 Provides `useAsync` hook for custom asynchronous logic
- 📦 Supports `ref` for manual revalidation and advanced use cases

## Installation
Install the package:
```bash
yarn add @gryfnie/react-asyncify
```

## Usage
```tsx
import React from 'react';
import { Async } from '@gryfnie/react-asyncify';

const fetchData = async () => {
  const response = await fetch('https://api.example.com/data');
  if (!response.ok) throw new Error('Failed to fetch data');
  return await response.json();
};

const MyComponent = () => {
  return (
    <Async
      resolve={fetchData}
      idleRender={() => <>Loading...</>}
      errorRender={(error) => <>{error.message}</>}
      onResolve={(data) => console.log(data)}
      onReject={(error) => console.log(error)}
      as={YourComponent}
    >
      {(props) => <>{props.data} {props.propsFromYourComponent}</>}
    </Async>
  );
};
export default MyComponent;
```

## API

### `Async` Component
The `Async` component accepts several props to handle different aspects of asynchronous operations in a React application.

#### Props
- **`resolve: () => Promise<T>`**
  **Required.** A function that returns a promise for fetching data. This function is called to retrieve the data when the component mounts or when revalidation occurs.

- **`idleRender: () => ReactNode`**
  **Required.** A function that returns a React node to be rendered while data is being loaded. This is typically used to display a loading spinner or message.

- **`errorRender: (error: Error) => ReactNode`**
  **Required.** A function that takes an error object as its argument and returns a React node to be rendered in case of an error. This is used to display error messages or fallback UI.

- **`children: (data: T) => ReactNode`**
  **Required.** A function that takes the resolved data as its argument and returns a React node to be rendered. This is the main content that will be displayed once the data is successfully fetched.

- **`revalidate?: number`**
  **Optional.** A number representing the interval in milliseconds at which the `resolve` function should be re-triggered to refresh the data. If not provided, the data will only be fetched once when the component mounts.

- **`as?: ElementType`**
  **Optional.** A React element type (e.g., `'div'`, `'section'`, `'span'`, `React.Fragment`, or a custom component) that determines what HTML element or component is rendered. Defaults to `React.Fragment`.

- **`onResolve?: (data: T) => void`**
  **Optional.** A callback function that is called when the data is successfully resolved. This can be used to perform side effects based on the retrieved data.

- **`onReject?: (error: Error) => void`**
  **Optional.** A callback function that is called when an error occurs during data fetching. This can be used to log errors or trigger other error-handling mechanisms.

- **`ref?: React.Ref<AsyncResolverHandle>`**
  **Optional.** A ref that can be used to manually trigger data revalidation by calling `handleRevalidate`. This is useful for advanced use cases where you need programmatic control over data fetching.

### `useAsync` Hook
The `useAsync` hook provides the same asynchronous handling capabilities as the `Async` component but allows you to implement custom logic within your own components.