PostHog React Native
Please see the main PostHog docs.
Specifically, the React Native integration details.
Questions?
Installation
Expo Apps
expo install posthog-react-native expo-file-system expo-application expo-device expo-localization
React Native Apps
yarn add posthog-react-native @react-native-async-storage/async-storage react-native-device-info
npm i -s posthog-react-native @react-native-async-storage/async-storage react-native-device-info
Usage
With the PosthogProvider
The best way to use PostHog is via the PosthogProvider which enables featues like Autocapture as well as providing posthog through your app via context.
import PostHog, { usePostHog } from 'posthog-react-native'
...
export function MyApp() {
return (
<PostHogProvider apiKey="<ph_project_api_key>" options={{
// (Optional) PostHog API host (https://app.posthog.com by default)
host: '<ph_instance_address>',
}}>
<MyComponent />
</PostHogProvider>
)
}
// Now you can simply access posthog elsewhere in the app like so
const MyComponent = () => {
const posthog = usePostHog()
useEffect(() => {
posthog.capture("MyComponent loaded", { foo: "bar" })
}, [])
}
Without the PosthogProvider
Due to the Async nature of React Native, PostHog needs to be initialised asynchronously in order for the persisted state to be loaded properly. The PosthogProvider takes care of this under-the-hood but you can alternatively create the instance yourself like so:
import PostHog from 'posthog-react-native'
export let posthog: PostHog | undefined = undefined
export const posthogPromise: Promise<PostHog> = PostHog.initAsync('<ph_project_api_key>', {
host: '<ph_instance_address>',
})
posthogPromise.then((client) => {
posthog = client
})
import { posthog, posthogPromise} from './posthog'
export function MyApp1() {
useEffect(() => {
posthog?.capture('MyApp1 loaded')
posthogPromise.then(ph => ph.capture('MyApp1 loaded')
}, [])
return <View>{...}</View>
}
export function MyApp2() {
return <PostHogProvider client={posthog}>{/* Your app code */}</PostHogProvider>
}
Implementing a custom solution for native dependencies
If you do not want to use either the expo libraries or the async-storage / react-native-device-info dependencies listed in the installation you can instead pass in the required information from whatever library you choose.
yarn add posthog-react-native
const customAppProperties = {
$app_build?: string | null,
$app_name?: string | null,
$app_namespace?: string | null,
$app_version?: string | null,
$device_manufacturer?: string | null,
$device_name?: string | null,
$os_name?: string | null,
$os_version?: string | null,
$locale?: string | null,
$timezone?: string | null
}
const posthog = new PostHog({
customAppProperties,
customAsyncStorage: {
getItem: (key: string): Promise<string | null> => { },
setItem (key: string, value: string): Promise<void> => { }
}
})
Development
Building and deploying
React Native uses Metro as it's bundling system which has some unique behaviors. As such we have to bundle this part of the project differently with special babel config and keeping the original file structure rather than rolling up to a single file. This is due to the way that Metro handles optional imports leading us to need multiple files rather than one bundle file.