> ## Documentation Index
> Fetch the complete documentation index at: https://replyke-feat-push-rich-payload-fields.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Infuse Data

# External Data Integration (infuseData)

The `infuseData` callback allows you to merge external data with entities fetched by Replyke. This is useful when your entities need additional information from external APIs or databases.

## How It Works

When you provide an `infuseData` function to `useEntityList`, it:

1. Receives the `foreignId` of each entity
2. Fetches additional data from your external source
3. Adds the external data under an `infusion` property
4. Returns the combined data in the `infusedEntities` array

The original `entities` array remains unchanged, containing only Replyke's data. External data is safely nested under the `infusion` property to prevent key conflicts.

## Usage

```typescript theme={null}
import { useEntityList } from "@replyke/core";

const ProductFeed = () => {
  const entityList = useEntityList({
    listId: "product-feed",
    infuseData: async (foreignId) => {
      try {
        const response = await fetch(`/api/inventory/${foreignId}`);
        return response.ok ? await response.json() : null;
      } catch (error) {
        console.error(`Failed to fetch inventory for ${foreignId}:`, error);
        return null;
      }
    }
  });

  useEffect(() => {
    entityList.fetchEntities(
      { sortBy: "hot" },
      { sourceId: "products", limit: 20 }
    );
  }, []);

  return (
    <div>
      {entityList.infusedEntities.map((entity) => (
        <div key={entity.id}>
          <h2>{entity.title}</h2>
          <p>{entity.content}</p>
          {/* External data is under the 'infusion' property */}
          <p>Stock: {entity.infusion?.stock}</p>
          <p>Price: ${entity.infusion?.price}</p>
        </div>
      ))}
    </div>
  );
};
```

## Performance

* Data is fetched once per entity and cached
* Failed fetches return `null` and don't block other entities
* The `infuseData` function is called automatically when new entities are loaded

## Use Cases

### Product Inventory

```typescript theme={null}
const infuseInventoryData = async (foreignId) => {
  const inventory = await fetch(`/api/inventory/${foreignId}`);
  return inventory.json(); // { stock: 25, price: 49.99, warehouse: "NYC" }
};
```

### User Profiles

```typescript theme={null}
const infuseUserData = async (foreignId) => {
  const profile = await fetch(`/api/users/${foreignId}`);
  return profile.json(); // { avatar: "...", verified: true, followers: 1250 }
};
```

### Analytics Data

```typescript theme={null}
const infuseAnalytics = async (foreignId) => {
  const stats = await fetch(`/api/analytics/${foreignId}`);
  return stats.json(); // { views: 5420, engagement: 0.12, trending: true }
};
```

## Error Handling

The `infuseData` function should handle errors gracefully:

```typescript theme={null}
const infuseData = async (foreignId) => {
  try {
    const response = await fetch(`/api/external/${foreignId}`);

    if (!response.ok) {
      console.warn(`External data not found for ${foreignId}`);
      return null;
    }

    return await response.json();
  } catch (error) {
    console.error(`Failed to fetch external data for ${foreignId}:`, error);
    return null; // Return null on error, don't throw
  }
};
```

## Data Structure

External data is safely nested under the `infusion` property to prevent conflicts with Replyke's entity properties:

```typescript theme={null}
// Original entity from Replyke
const entity = {
  id: "123",
  foreignId: "product-456",
  title: "Amazing Widget",
  content: "A great product...",
  // ... other Replyke fields
};

// External data returned by infuseData
const externalData = {
  stock: 25,
  price: 49.99,
  warehouse: "NYC"
};

// Final result in infusedEntities
const infusedEntity = {
  id: "123",
  foreignId: "product-456",
  title: "Amazing Widget",
  content: "A great product...",
  // External data safely nested under 'infusion'
  infusion: {
    stock: 25,
    price: 49.99,
    warehouse: "NYC"
  }
};
```

## Accessing Infused Data

Always access external data through the `infusion` property:

```typescript theme={null}
// ✅ Correct - access via infusion property
entity.infusion?.stock
entity.infusion?.price
entity.infusion?.warehouse

// ❌ Wrong - external data is not merged at root level
entity.stock // undefined
entity.price // undefined
```

## Handling Missing Data

Since external data fetching can fail, always use optional chaining:

```typescript theme={null}
{entityList.infusedEntities.map(entity => (
  <div key={entity.id}>
    <h2>{entity.title}</h2>
    {entity.infusion ? (
      <div>
        <p>Stock: {entity.infusion.stock}</p>
        <p>Price: ${entity.infusion.price}</p>
      </div>
    ) : (
      <p>External data unavailable</p>
    )}
  </div>
))}
```
