Troubleshooting
Inbox Not Updating in Real-time
Symptom: Inbox shows messages on initial load but doesn’t update when new messages arrive.
Solution: Make sure you’ve called inbox.listenForUpdates() after authentication. This establishes the WebSocket connection required for real-time updates.
// Correct setup order:
await auth.signIn({ userId, jwt });
await inbox.registerFeeds(defaultFeeds());
await inbox.listenForUpdates(); // ← REQUIRED for real-time updates
await inbox.load();
Without listenForUpdates(), the inbox will only show messages from the initial load and won’t receive real-time updates via WebSocket.
Messages Not Loading
Possible Causes:
- Not authenticated: Ensure
auth.signIn() or courier.shared.signIn() has been called
- Feeds not registered: Call
inbox.registerFeeds() before inbox.load()
- Network errors: Check
inbox.error for error details
- JWT expired: Generate a new JWT token
Debugging:
const { inbox } = useCourier();
if (inbox.error) {
console.error('Inbox error:', inbox.error);
}
Authentication Errors
Common Issues:
- Invalid JWT: Ensure the JWT is generated correctly on your backend
- Expired JWT: JWTs have an expiration time. Generate a new one if expired
- Missing scopes: Ensure your JWT includes required scopes like
inbox:read:messages
- Wrong user ID: Verify the
userId matches the user the JWT was issued for
Solution: Check the browser console for authentication errors and verify your JWT generation endpoint.
TypeScript Errors
Common Issues:
- Missing type imports: Import types from
@trycourier/courier-react
- Type mismatches: Ensure you’re using the correct types (e.g.,
InboxMessage, CourierInboxFeed)
Solution:
import {
useCourier,
type InboxMessage,
type CourierInboxFeed
} from '@trycourier/courier-react';
React 17 vs React 18 Issues
Package Mismatch: Ensure you’re using the correct package:
- React 18+:
@trycourier/courier-react
- React 17:
@trycourier/courier-react-17
Solution: Check your package.json and ensure the React version matches the Courier package version.
Best Practices
JWT Security
- Always generate JWTs server-side: Never expose your Courier API key in client-side code
- Cache JWTs on the client: After receiving a JWT from your backend, cache it to avoid unnecessary requests
- Refresh before expiration: Generate new JWTs before the current one expires
- Use appropriate expiration: Standard expiration is
'1d' (1 day) for typical web apps
- Include only necessary scopes: Only request the scopes your app actually needs
Error Handling
- Check error properties: Always check
inbox.error and toast.error for error states
- Handle errors gracefully: Show user-friendly error messages instead of raw error objects
- Implement retry logic: For transient errors, implement retry logic with exponential backoff
- Log errors for debugging: Use
showLogs: true during development to see detailed error information
const { inbox } = useCourier();
useEffect(() => {
if (inbox.error) {
// Handle error
console.error('Inbox error:', inbox.error);
// Show user-friendly message
}
}, [inbox.error]);
- Use
canUseCache wisely: The default is true, which uses cached data. Set to false only when you need fresh data
- Load specific datasets: Use
datasetIds parameter to load only the datasets you need
- Set pagination limits: Use
setPaginationLimit() to control how many messages load per page
- Avoid unnecessary re-renders: The hook’s reactive state updates automatically - don’t manually trigger re-renders
// Load only specific datasets for better performance
await inbox.load({ datasetIds: ['inbox', 'archive'] });
// Set appropriate pagination limit
inbox.setPaginationLimit(20); // Load 20 messages per page
Accessibility
- Provide alternative text: When customizing list items, ensure images and icons have alt text
- Keyboard navigation: Ensure custom UI elements are keyboard accessible
- Screen reader support: Test with screen readers and provide appropriate ARIA labels
- Color contrast: Ensure custom themes meet WCAG contrast requirements
Testing
- Mock the hook: In tests, mock
useCourier() to return test data
- Test error states: Ensure your UI handles error states correctly
- Test loading states: Verify loading indicators work properly
- Test real-time updates: Use WebSocket mocks to test real-time functionality
// Example test setup
jest.mock('@trycourier/courier-react', () => ({
useCourier: () => ({
inbox: {
feeds: { 'all_messages': { messages: mockMessages } },
totalUnreadCount: 5
}
})
}));
Next.js and Server Side Rendering Frameworks
Both Courier Inbox and Courier Toast support Next.js, however the components only support client side rendering.
In Next.js version 13+, make sure to add the 'use client'
directive to the top of any file that uses Courier components.
"use client"
import { CourierInbox } from "@trycourier/courier-react";
export default function Page() {
// Courier authentication and other component code...
return <CourierInbox />;
}