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:
- Receives the
foreignId
of each entity - Fetches additional data from your external source
- Adds the external data under an
infusion
property - 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
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
const infuseInventoryData = async (foreignId) => {
const inventory = await fetch(`/api/inventory/${foreignId}`);
return inventory.json(); // { stock: 25, price: 49.99, warehouse: "NYC" }
};
User Profiles
const infuseUserData = async (foreignId) => {
const profile = await fetch(`/api/users/${foreignId}`);
return profile.json(); // { avatar: "...", verified: true, followers: 1250 }
};
Analytics Data
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:
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:
// 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:
// ✅ 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:
{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>
))}