Skip to content

Commit bc38856

Browse files
sherwinskifadi-george
authored andcommitted
chore(examples): fix fetcing user data on login
1 parent c1c24a7 commit bc38856

File tree

3 files changed

+52
-26
lines changed

3 files changed

+52
-26
lines changed

examples/RNOneSignalTS/OSDemo.tsx

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,30 @@ function OSDemoContent() {
6666
*/
6767
const fetchAndPopulateUserData = useCallback(async () => {
6868
try {
69-
const onesignalId = OneSignal.User.onesignalId;
69+
// Use async getOnesignalId() method (not the non-existent sync property)
70+
let onesignalId: string | null = null;
71+
try {
72+
onesignalId = await OneSignal.User.getOnesignalId();
73+
} catch {
74+
OSLog('SDK not ready yet, cannot get OneSignal ID');
75+
return;
76+
}
77+
7078
if (!onesignalId) {
7179
OSLog('No OneSignal ID found, skipping data fetch');
7280
return;
7381
}
7482

75-
OSLog('Fetching user data from API...');
83+
OSLog(`Fetching user data for ID: ${onesignalId}`);
7684
dispatch({ type: 'SET_LOADING', payload: true });
7785

7886
const userData = await fetchUserData(onesignalId);
7987

88+
OSLog(
89+
`Fetched: ${userData.aliases.length} aliases, ${userData.tags.length} tags, ` +
90+
`${userData.emails.length} emails, ${userData.smsNumbers.length} SMS`,
91+
);
92+
8093
// Populate state with fetched data
8194
dispatch({ type: 'SET_ALL_ALIASES', payload: userData.aliases });
8295
dispatch({ type: 'SET_ALL_TAGS', payload: userData.tags });
@@ -88,9 +101,6 @@ function OSDemoContent() {
88101
}
89102

90103
OSLog('User data loaded successfully');
91-
92-
// Add 100ms delay to ensure UI has time to render
93-
await new Promise((resolve) => setTimeout(resolve, 100));
94104
} catch (error) {
95105
OSLog('Failed to fetch user data: ', error);
96106
} finally {
@@ -173,10 +183,11 @@ function OSDemoContent() {
173183
);
174184

175185
const onUserChange = useCallback(
176-
(event: unknown) => {
186+
async (event: unknown) => {
177187
OSLog('OneSignal: user changed: ', event);
178-
// Fetch user data when user changes
179-
fetchAndPopulateUserData();
188+
// Small delay to let SDK finalize user state before querying ID
189+
await new Promise((resolve) => setTimeout(resolve, 1000));
190+
await fetchAndPopulateUserData();
180191
},
181192
[OSLog, fetchAndPopulateUserData],
182193
);
@@ -185,27 +196,24 @@ function OSDemoContent() {
185196
OneSignal.initialize(APP_ID);
186197
OneSignal.Debug.setLogLevel(LogLevel.None);
187198

188-
// Fetch user data on cold start with retry mechanism
189-
// OneSignal ID might not be available immediately after initialization
199+
// Wait for SDK native init to complete, then fetch user data if available.
200+
// Unlike Flutter's `await OneSignal.initialize()`, RN's initialize() is
201+
// fire-and-forget, so we must wait before calling any SDK methods.
190202
const initUserData = async () => {
191-
// Try up to 5 times with increasing delays
192-
const maxRetries = 5;
193-
const baseDelay = 500; // Start with 500ms
203+
// Give the native SDK time to initialize
204+
await new Promise((resolve) => setTimeout(resolve, 3000));
194205

195-
for (let attempt = 0; attempt < maxRetries; attempt++) {
196-
const onesignalId = OneSignal.User.onesignalId;
206+
try {
207+
const onesignalId = await OneSignal.User.getOnesignalId();
197208
if (onesignalId) {
198-
fetchAndPopulateUserData();
199-
return;
209+
console.log(`[Init] OneSignal ID found: ${onesignalId}`);
210+
await fetchAndPopulateUserData();
211+
} else {
212+
console.log('[Init] No OneSignal ID yet — will fetch on user change event');
200213
}
201-
202-
// Wait before next attempt (exponential backoff)
203-
const delay = baseDelay * Math.pow(2, attempt);
204-
await new Promise((resolve) => setTimeout(resolve, delay));
214+
} catch (e) {
215+
console.log('[Init] SDK not ready for getOnesignalId(), will rely on user change event');
205216
}
206-
207-
// After all retries, log that we couldn't get the ID
208-
console.log('OneSignal ID not available after retries, waiting for user change event');
209217
};
210218
initUserData();
211219
}, [fetchAndPopulateUserData]);
@@ -343,7 +351,7 @@ function OSDemoContent() {
343351
<ScrollView style={styles.scrollView}>
344352
{/* Section Order matching Android V2 */}
345353
<AppInfoSection loggingFunction={OSLog} />
346-
<UserSection loggingFunction={OSLog} />
354+
<UserSection loggingFunction={OSLog} onUserDataRefresh={fetchAndPopulateUserData} />
347355
<PushSubscriptionSection loggingFunction={OSLog} />
348356
<NotificationDemoSection loggingFunction={OSLog} />
349357
<InAppMessagingSection loggingFunction={OSLog} />

examples/RNOneSignalTS/bun.lockb

280 Bytes
Binary file not shown.

examples/RNOneSignalTS/components/sections/UserSection.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import { useAppState } from '../../context/AppStateContext';
1010

1111
interface UserSectionProps {
1212
loggingFunction: (message: string, optionalArg?: unknown) => void;
13+
onUserDataRefresh?: () => Promise<void>;
1314
}
1415

15-
export function UserSection({ loggingFunction }: UserSectionProps) {
16+
export function UserSection({ loggingFunction, onUserDataRefresh }: UserSectionProps) {
1617
const { state, dispatch } = useAppState();
1718
const [loginDialogVisible, setLoginDialogVisible] = useState(false);
1819

@@ -24,6 +25,20 @@ export function UserSection({ loggingFunction }: UserSectionProps) {
2425
try {
2526
await OneSignal.login(externalId);
2627
dispatch({ type: 'SET_EXTERNAL_USER_ID', payload: externalId });
28+
loggingFunction('Login successful for: ' + externalId);
29+
30+
// After login, wait for SDK to associate the user, then fetch data.
31+
// This mirrors the Flutter demo's approach where the observer
32+
// triggers fetchUserDataFromApi() after login.
33+
if (onUserDataRefresh) {
34+
// Give SDK time to finalize the user identity
35+
await new Promise((resolve) => setTimeout(resolve, 2000));
36+
try {
37+
await onUserDataRefresh();
38+
} catch (e) {
39+
loggingFunction('Data refresh after login failed, will retry on user change event');
40+
}
41+
}
2742
} finally {
2843
dispatch({ type: 'SET_LOADING', payload: false });
2944
}
@@ -34,11 +49,14 @@ export function UserSection({ loggingFunction }: UserSectionProps) {
3449
dispatch({ type: 'SET_LOADING', payload: true });
3550
try {
3651
await OneSignal.logout();
52+
// Clear all user-specific state (matching Flutter demo behavior)
3753
dispatch({ type: 'SET_EXTERNAL_USER_ID', payload: null });
3854
dispatch({ type: 'CLEAR_ALL_ALIASES' });
55+
dispatch({ type: 'SET_ALL_TAGS', payload: [] });
3956
dispatch({ type: 'SET_ALL_EMAILS', payload: [] });
4057
dispatch({ type: 'SET_ALL_SMS', payload: [] });
4158
dispatch({ type: 'CLEAR_ALL_TRIGGERS' });
59+
loggingFunction('Logged out successfully');
4260
} finally {
4361
dispatch({ type: 'SET_LOADING', payload: false });
4462
}

0 commit comments

Comments
 (0)