useFetchConnectionsByUserId
Overview
The useFetchConnectionsByUserId
hook fetches the list of established connections for any specified user. This is a public endpoint that allows you to view any user’s connections with pagination support, making it useful for exploring networks and discovering mutual connections.
Usage Example
import { useFetchConnectionsByUserId } from "@replyke/react-js";
function UserConnectionsList({ targetUserId }: { targetUserId: string }) {
const fetchConnectionsByUserId = useFetchConnectionsByUserId();
const loadUserConnections = async () => {
try {
const result = await fetchConnectionsByUserId({
userId: targetUserId,
page: 1,
limit: 15
});
console.log(`This user has ${result.pagination.totalCount} connections`);
result.connections.forEach(connection => {
console.log(`Connected to ${connection.user.username} since ${connection.connectedAt}`);
});
} catch (error) {
console.error("Failed to fetch user connections:", error.message);
}
};
return <button onClick={loadUserConnections}>View Connections</button>;
}
Advanced Usage with State Management
import { useFetchConnectionsByUserId, ConnectionsResponse } from "@replyke/react-js";
import { useState, useEffect } from "react";
function UserNetworkExplorer({
userId,
username
}: {
userId: string;
username: string;
}) {
const fetchConnectionsByUserId = useFetchConnectionsByUserId();
const [connectionsData, setConnectionsData] = useState<ConnectionsResponse | null>(null);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
useEffect(() => {
const loadConnections = async () => {
if (!userId) return;
setLoading(true);
try {
const result = await fetchConnectionsByUserId({
userId,
page: currentPage,
limit: 12
});
setConnectionsData(result);
} catch (error) {
console.error("Failed to load user connections:", error);
} finally {
setLoading(false);
}
};
loadConnections();
}, [userId, currentPage, fetchConnectionsByUserId]);
return (
<div className="user-network-explorer">
<h2>{username}'s Network ({connectionsData?.pagination.totalCount || 0})</h2>
{loading ? (
<div>Loading connections...</div>
) : (
<>
<div className="connections-grid">
{connectionsData?.connections.map(connection => (
<div key={connection.id} className="connection-card">
<div className="user-info">
<h4>{connection.user.displayName || connection.user.username}</h4>
<p>@{connection.user.username}</p>
<small>
Connected: {new Date(connection.connectedAt).toLocaleDateString()}
</small>
</div>
</div>
))}
</div>
{connectionsData && connectionsData.pagination.totalPages > 1 && (
<div className="pagination">
<button
disabled={!connectionsData.pagination.hasPreviousPage || loading}
onClick={() => setCurrentPage(prev => prev - 1)}
>
Previous
</button>
<span>
Page {connectionsData.pagination.currentPage} of {connectionsData.pagination.totalPages}
</span>
<button
disabled={!connectionsData.pagination.hasNextPage || loading}
onClick={() => setCurrentPage(prev => prev + 1)}
>
Next
</button>
</div>
)}
</>
)}
</div>
);
}
Usage for Mutual Connections Discovery
import { useFetchConnectionsByUserId } from "@replyke/react-js";
import { useFetchConnections } from "@replyke/react-js";
import { useState, useEffect, useMemo } from "react";
function MutualConnectionsFinder({ targetUserId, targetUsername }: { targetUserId: string; targetUsername: string }) {
const fetchConnectionsByUserId = useFetchConnectionsByUserId();
const fetchMyConnections = useFetchConnections();
const [targetUserConnections, setTargetUserConnections] = useState<any[]>([]);
const [myConnections, setMyConnections] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
const loadAllConnections = async () => {
setLoading(true);
try {
// Load target user's connections
let targetConnections: any[] = [];
let currentPage = 1;
let hasMore = true;
while (hasMore) {
const result = await fetchConnectionsByUserId({
userId: targetUserId,
page: currentPage,
limit: 50
});
targetConnections = [...targetConnections, ...result.connections];
hasMore = result.pagination.hasNextPage;
currentPage++;
}
// Load my connections
let myConnectionsList: any[] = [];
currentPage = 1;
hasMore = true;
while (hasMore) {
const result = await fetchMyConnections({ page: currentPage, limit: 50 });
myConnectionsList = [...myConnectionsList, ...result.connections];
hasMore = result.pagination.hasNextPage;
currentPage++;
}
setTargetUserConnections(targetConnections);
setMyConnections(myConnectionsList);
} catch (error) {
console.error("Failed to load connections for mutual analysis:", error);
} finally {
setLoading(false);
}
};
loadAllConnections();
}, [targetUserId]);
const mutualConnections = useMemo(() => {
const myConnectionUserIds = new Set(myConnections.map(conn => conn.user.id));
return targetUserConnections.filter(conn => myConnectionUserIds.has(conn.user.id));
}, [targetUserConnections, myConnections]);
return (
<div className="mutual-connections-finder">
<h3>Mutual Connections with {targetUsername}</h3>
{loading ? (
<div>Analyzing connections...</div>
) : (
<>
<div className="mutual-stats">
<p>
You and {targetUsername} have <strong>{mutualConnections.length}</strong> mutual connections
</p>
</div>
{mutualConnections.length > 0 ? (
<div className="mutual-connections-list">
{mutualConnections.map(connection => (
<div key={connection.id} className="mutual-connection-card">
<div className="user-info">
<h4>{connection.user.displayName || connection.user.username}</h4>
<p>@{connection.user.username}</p>
</div>
<div className="connection-badge">
<span>Mutual Connection</span>
</div>
</div>
))}
</div>
) : (
<div className="no-mutual-connections">
<p>No mutual connections found yet.</p>
</div>
)}
</>
)}
</div>
);
}
Usage in User Discovery
import { useFetchConnectionsByUserId } from "@replyke/react-js";
import { useState } from "react";
function NetworkDiscovery({ seedUserId }: { seedUserId: string }) {
const fetchConnectionsByUserId = useFetchConnectionsByUserId();
const [discoveredUsers, setDiscoveredUsers] = useState<Map<string, any>>(new Map());
const [explorationDepth, setExplorationDepth] = useState(0);
const [exploring, setExploring] = useState(false);
const exploreNetwork = async (userId: string, depth: number = 0, maxDepth: number = 2) => {
if (depth > maxDepth || discoveredUsers.has(userId)) return;
setExploring(true);
try {
const result = await fetchConnectionsByUserId({
userId,
page: 1,
limit: 20 // Limit to prevent too many API calls
});
// Add discovered users to our map
const newDiscovered = new Map(discoveredUsers);
result.connections.forEach(connection => {
if (!newDiscovered.has(connection.user.id)) {
newDiscovered.set(connection.user.id, {
...connection.user,
connectionDepth: depth + 1,
discoveredThrough: userId
});
}
});
setDiscoveredUsers(newDiscovered);
setExplorationDepth(depth + 1);
// Recursively explore some of the connections (limit to prevent explosion)
const connectionsToExplore = result.connections.slice(0, 3);
for (const connection of connectionsToExplore) {
await exploreNetwork(connection.user.id, depth + 1, maxDepth);
// Add delay to be respectful to the API
await new Promise(resolve => setTimeout(resolve, 1000));
}
} catch (error) {
console.error(`Failed to explore network for user ${userId}:`, error);
} finally {
setExploring(false);
}
};
const startExploration = () => {
setDiscoveredUsers(new Map());
setExplorationDepth(0);
exploreNetwork(seedUserId);
};
const getUsersByDepth = (depth: number) => {
return Array.from(discoveredUsers.values()).filter(user => user.connectionDepth === depth);
};
return (
<div className="network-discovery">
<div className="discovery-controls">
<h3>Network Discovery</h3>
<button onClick={startExploration} disabled={exploring}>
{exploring ? "Exploring..." : "Start Network Exploration"}
</button>
</div>
{discoveredUsers.size > 0 && (
<div className="discovery-results">
<h4>Discovered {discoveredUsers.size} users</h4>
{[1, 2, 3].map(depth => {
const usersAtDepth = getUsersByDepth(depth);
if (usersAtDepth.length === 0) return null;
return (
<div key={depth} className="depth-section">
<h5>
{depth === 1 && "Direct Connections"}
{depth === 2 && "Friends of Friends"}
{depth === 3 && "Extended Network"}
{` (${usersAtDepth.length})`}
</h5>
<div className="users-grid">
{usersAtDepth.map(user => (
<div key={user.id} className="discovered-user-card">
<h6>{user.displayName || user.username}</h6>
<p>@{user.username}</p>
<small>Depth: {user.connectionDepth}</small>
</div>
))}
</div>
</div>
);
})}
</div>
)}
</div>
);
}
Usage with Analytics and Insights
import { useFetchConnectionsByUserId } from "@replyke/react-js";
import { useState, useEffect } from "react";
interface NetworkAnalytics {
totalConnections: number;
averageConnectionsPerMonth: number;
topConnectionDomains: Array<{ domain: string; count: number }>;
connectionGrowthTrend: Array<{ month: string; count: number }>;
}
function UserNetworkAnalytics({ userId, username }: { userId: string; username: string }) {
const fetchConnectionsByUserId = useFetchConnectionsByUserId();
const [analytics, setAnalytics] = useState<NetworkAnalytics | null>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
const analyzeNetwork = async () => {
setLoading(true);
try {
// Load all connections for analysis
let allConnections: any[] = [];
let currentPage = 1;
let hasMore = true;
while (hasMore) {
const result = await fetchConnectionsByUserId({
userId,
page: currentPage,
limit: 100
});
allConnections = [...allConnections, ...result.connections];
hasMore = result.pagination.hasNextPage;
currentPage++;
}
// Perform analytics calculations
const totalConnections = allConnections.length;
// Calculate average connections per month
if (allConnections.length > 0) {
const oldestConnection = allConnections.reduce((oldest, conn) =>
new Date(conn.connectedAt) < new Date(oldest.connectedAt) ? conn : oldest
);
const monthsSinceFirst = (Date.now() - new Date(oldestConnection.connectedAt).getTime()) / (1000 * 60 * 60 * 24 * 30);
const averageConnectionsPerMonth = totalConnections / Math.max(monthsSinceFirst, 1);
// Analyze domains (if email data is available)
const domainCounts: { [key: string]: number } = {};
allConnections.forEach(conn => {
if (conn.user.email) {
const domain = conn.user.email.split('@')[1];
domainCounts[domain] = (domainCounts[domain] || 0) + 1;
}
});
const topConnectionDomains = Object.entries(domainCounts)
.map(([domain, count]) => ({ domain, count }))
.sort((a, b) => b.count - a.count)
.slice(0, 5);
// Calculate growth trend by month
const connectionsByMonth: { [key: string]: number } = {};
allConnections.forEach(conn => {
const monthKey = new Date(conn.connectedAt).toISOString().slice(0, 7); // YYYY-MM
connectionsByMonth[monthKey] = (connectionsByMonth[monthKey] || 0) + 1;
});
const connectionGrowthTrend = Object.entries(connectionsByMonth)
.map(([month, count]) => ({ month, count }))
.sort((a, b) => a.month.localeCompare(b.month))
.slice(-12); // Last 12 months
setAnalytics({
totalConnections,
averageConnectionsPerMonth: Math.round(averageConnectionsPerMonth * 100) / 100,
topConnectionDomains,
connectionGrowthTrend
});
}
} catch (error) {
console.error("Failed to analyze network:", error);
} finally {
setLoading(false);
}
};
analyzeNetwork();
}, [userId]);
if (loading) return <div>Analyzing {username}'s network...</div>;
if (!analytics) return <div>Unable to analyze network</div>;
return (
<div className="network-analytics">
<h3>{username}'s Network Analytics</h3>
<div className="analytics-grid">
<div className="stat-card">
<h4>Total Connections</h4>
<div className="stat-number">{analytics.totalConnections.toLocaleString()}</div>
</div>
<div className="stat-card">
<h4>Monthly Average</h4>
<div className="stat-number">{analytics.averageConnectionsPerMonth}</div>
<small>connections per month</small>
</div>
{analytics.topConnectionDomains.length > 0 && (
<div className="stat-card">
<h4>Top Connection Domains</h4>
<ul className="domain-list">
{analytics.topConnectionDomains.map(({ domain, count }) => (
<li key={domain}>
{domain}: {count}
</li>
))}
</ul>
</div>
)}
{analytics.connectionGrowthTrend.length > 0 && (
<div className="stat-card">
<h4>Recent Activity</h4>
<div className="growth-chart">
{analytics.connectionGrowthTrend.slice(-6).map(({ month, count }) => (
<div key={month} className="month-bar">
<div className="bar" style={{ height: `${(count / Math.max(...analytics.connectionGrowthTrend.map(t => t.count))) * 100}px` }} />
<small>{month.slice(-2)}</small>
</div>
))}
</div>
</div>
)}
</div>
</div>
);
}
Parameters & Returns
Parameters
The hook returns a function that accepts an object with the following fields:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
userId | string | Yes | - | The ID of the user whose connections to fetch |
page | number | No | 1 | Page number for pagination |
limit | number | No | 20 | Number of connections to return per page |
Returns
The function returns a Promise that resolves to a ConnectionsResponse
object containing:
ConnectionsResponse
Field | Type | Description |
---|---|---|
connections | Connection[] | Array of connection information |
pagination | PaginationInfo | Pagination metadata |
Connection
Field | Type | Description |
---|---|---|
id | string | Unique ID of the connection relationship |
user | User | User object containing connected user information |
connectedAt | string | ISO date string of when the connection was established |
requestedAt | string | ISO date string of when the connection was initially requested |
PaginationInfo
Field | Type | Description |
---|---|---|
currentPage | number | Current page number |
totalPages | number | Total number of pages available |
totalCount | number | Total number of connections for this user |
hasNextPage | boolean | Whether there are more pages after current page |
hasPreviousPage | boolean | Whether there are pages before current page |
limit | number | Number of items per page used in this request |
Error Handling
The hook will throw errors in the following cases:
- No project is specified
- No user ID is provided
- Network connection issues
Use Cases
This hook is perfect for:
Social Discovery:
- Exploring user networks and finding mutual connections
- User recommendation systems
- Professional networking features
Analytics & Insights:
- Network analysis and visualization
- Connection pattern analysis
- Social graph exploration
Public Profiles:
- Displaying user connections on profile pages
- Professional networking showcases
- Community member directories
Privacy Considerations
Since this is a public endpoint, consider:
- Implementing privacy settings for users who want to hide their connections
- Rate limiting to prevent abuse
- Respecting user privacy preferences
- Providing opt-out mechanisms
Related Hooks
useFetchConnections
- Get connections for current user (authenticated)useFetchConnectionsCountByUserId
- Get connection count for any useruseFetchConnectionStatus
- Check connection status with specific useruseConnectionManager
- Comprehensive connection state management