Fix frozen unknown device ID for new accounts (#11449)
This commit is contained in:
@@ -224,6 +224,7 @@ return conditional styles inline in a style array: `web({cursor: 'pointer'})`,
|
||||
- Prefer prop destructuring via parameters over a const within the component.
|
||||
- Prefer inline types over `Props` types or interfaces.
|
||||
- Set reasonable defaults for optional props.
|
||||
- Prefer the implicit global `React` for types over `type` imports.
|
||||
|
||||
```tsx
|
||||
import {Fragment} from 'react'
|
||||
@@ -232,7 +233,13 @@ import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
function MyComponent({items = []}: {items?: string[]}) {
|
||||
function MyComponent({
|
||||
items = [],
|
||||
children,
|
||||
}: {
|
||||
items?: string[]
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<View>
|
||||
@@ -247,6 +254,7 @@ function MyComponent({items = []}: {items?: string[]}) {
|
||||
<Text>{item}</Text>
|
||||
</Fragment>
|
||||
))}
|
||||
{children}
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {useSyncExternalStore} from 'react'
|
||||
import uuid from 'react-native-uuid'
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
|
||||
@@ -24,3 +25,23 @@ export function getDeviceIdOrThrow() {
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
function subscribeToDeviceId(onChange: () => void) {
|
||||
const sub = device.addOnValueChangedListener(['deviceId'], onChange)
|
||||
return () => sub.remove()
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the device ID for use during render. The app awaits
|
||||
* `getAndMigrateDeviceId` before booting (see `setupDeviceId` in
|
||||
* `analytics/index.tsx`), so this is normally set on first read.
|
||||
*
|
||||
* Subscribing rather than reading storage directly means a late write - a
|
||||
* caller that mounts before the migration resolves - still propagates, instead
|
||||
* of leaving consumers pinned to `undefined` for the lifetime of the component.
|
||||
* `useSyncExternalStore` re-evaluates the snapshot every render, so there's no
|
||||
* gap between the initial read and the subscription.
|
||||
*/
|
||||
export function useDeviceId() {
|
||||
return useSyncExternalStore(subscribeToDeviceId, getDeviceId)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
getAndMigrateDeviceId,
|
||||
getDeviceId,
|
||||
getInitialSessionId,
|
||||
useDeviceId,
|
||||
useSessionId,
|
||||
} from '#/analytics/identifiers'
|
||||
import {
|
||||
@@ -178,6 +179,7 @@ export function AnalyticsContext({
|
||||
)
|
||||
}
|
||||
}
|
||||
const deviceId = useDeviceId() ?? 'unknown'
|
||||
const sessionId = useSessionId()
|
||||
const geolocation = useGeolocationServiceResponse()
|
||||
const parentContext = useContext(Context)
|
||||
@@ -197,6 +199,7 @@ export function AnalyticsContext({
|
||||
...metadata,
|
||||
base: {
|
||||
...parentContext.metadata.base,
|
||||
deviceId,
|
||||
sessionId,
|
||||
isBetaUser,
|
||||
},
|
||||
@@ -217,7 +220,7 @@ export function AnalyticsContext({
|
||||
},
|
||||
}
|
||||
return context
|
||||
}, [parentContext, metadata, sessionId, isBetaUser, geolocation])
|
||||
}, [parentContext, metadata, deviceId, sessionId, isBetaUser, geolocation])
|
||||
return <Context.Provider value={childContext}>{children}</Context.Provider>
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user