Visualizing Sahha Scores in React-Native (TypeScript)
In this tutorial, we will walk through the process of visualizing health-related data using Sahha in a React Native application. We will use react-native-gifted-charts
for rendering bar charts and sahha-react-native
for gathering the data. The steps below will guide you through setting up the project, configuring Sahha, authenticating the user, and displaying the data.
Prerequisites
Before we begin, ensure you have the following:
- Basic knowledge of React Native and TypeScript.
- Node.js installed on your machine.
- React Native CLI installed.
- A Sahha account and API keys.
Setting Up Your React Native Project
First, initialize your React Native project:
npx react-native init SahhaVisualization cd SahhaVisualization
Install the necessary dependencies:
npm install sahha-react-native react-native-config react-native-gifted-charts date-fns
Dependencies explained:
sahha-react-native
: The Sahha SDK for integrating their behavioral health insights API into React Native apps, enabling analysis and visualization of health data.react-native-config
: Manages environment variables in React Native apps, allowing you to store and access configuration settings securely.react-native-gifted-charts
: A library for rendering beautiful and customizable charts in React Native applications.date-fns
: A modern JavaScript date utility library for date manipulation, providing a wide range of functions to work with dates.Configuring the Sahha SDK
Create a
.env
file in the root of your project and add your Sahha API credentials:SAHHA_APPLICATION_ID=your_application_id SAHHA_APPLICATION_SECRET=your_application_secret
Next inside the App.tsx file we want to add the following configuration object to the top of the file after our imports:
const SAHHA_CONFIGURATION_SETTINGS = { environment: SahhaEnvironment.sandbox, };
This is a minimal configuration object, you can see all of the available configuration settings in the Sahha documentation.
We then need to call the configure function from the Sahha SDK, to keep things tidy I am going to create a wrapper function to convert the
Sahha.configure
function into a promise so we can useasync await
syntax.javascript
const configureSahha = () => new Promise((resolve, reject) => Sahha.configure( SAHHA_CONFIGURATION_SETTINGS, (error: string, success: boolean) => { if (success) resolve(success); reject(error); }, ), );
And then inside the render function of our App.tsx file I am going to create a
useEffect
with an empty dependency array so that it runs once on app start. We then need to add ourconfigureSahha
wrapper function, as it is an async function we also need to wrap it in an immediately-invoked async function expression and a try catch block.Our
useEffect
should now look like this:javascript
useEffect(() => { (async () => { try { await configureSahha(); } catch (e) { console.error(e); } })(); }, []);
Authenticating the Sahha SDK
Now we have successfully configured the Sahha SDK, we need to authenticate so we can retrieve data for a profile. For this you will need your
applicationID
andapplicationSecret
. You can find these values in the credentials section of the Sahha dashboard.To authenticate we need to call the authenticate function from the Sahha SDK, just like the configure function I am again going to create a wrapper function to convert the
Sahha.authenticate
function into a promise so we can use async await syntax.javascript
const authenticateSahha = (externalId: string) => new Promise((resolve, reject) => Sahha.authenticate( Config.SAHHA_APPLICATION_ID || '', Config.SAHHA_APPLICATION_SECRET || '', externalId, (error, success) => { if (success) resolve(success); reject(error); }, ), );
Once we have added this function, we can then add it to our
useEffect
inside the render function.javascript
useEffect(() => { (async () => { try { await configureSahha(); await authenticateSahha('your-external-id'); } catch (e) { console.error(e); } })(); }, []);
Be sure to replace the ‘your-external-id’ string to the external ID of the profile you want to authenticate.
Retrieving Health Score data from the Sahha SDK
Now that we have configured and authenticated the Sahha SDK, we can start retrieving Health Score data.
Before we retrieve any data, I am going to add the type definition for the response from the Sahha analyzeDateRange function.
javascript
type SahhaScore = { id: string; type: string; state: string; score: number; factors: { name: string; value: number; }[]; inputData: string[]; createdAt: string; }; type SahhaAnalyzeResponse = { inferences?: SahhaScore[] }
This is a loose type definition, You can find more information about the shape of the response in the Scores & Insights section of the Sahha documentation.
Once we have the type definitions we are going to create another wrapper function for the
sahha.analyzeDateRange
function.javascript
const analyzeSahhaDateRange = ( startDate: Date, endDate: Date, ): Promise<SahhaAnalyzeResponse> => new Promise((resolve, reject) => Sahha.analyzeDateRange( startDate.getTime(), endDate.getTime(), (error, value) => { try { if (error) throw new Error(error); resolve(JSON.parse(value)); } catch (e) { reject(e); } }, ), );
We will then get our startDate and endDate, for this I am going to use
date-fns
but you can use any date library you prefer, or plain JS Date obejcts.We are going to get set our end date as the current date and our start date as 6 days ago giving us a one week date range. We will also get all the dates between those values for our chart will always have 7 days.
Place this code at the top of your render function in your App.tsx file:
javascript
const end = new Date(); const start = subDays(end, 6); const days = eachDayOfInterval({start, end});
We can then call our wrapper function inside the
useEffect
after the other two function calls:javascript
useEffect(() => { (async () => { try { await configureSahha(); await authenticateSahha('healthy-profile-01'); const {inferences} = await analyzeSahhaDateRange(start, end); } catch (e) { console.error(e); } })(); }, []);
💡 The analysis engine requires a minimum amount of device sensor data to be uploaded and processed before an analysis can be determined.
If you call
analyze
for a new user profile or a user that has been inactive lately, it's possible for the response to be204 No Content
. This is not an error.You will need to wait and try again every 24 hours until an analysis is available.
Visualizing Sahha Wellbeing Scores in a bar chart
Now we are getting our Health Score data back form the Sahha SDK for our date range we can add a chart to visualize it.
As the
sahha.analyzeDateRange
function returns all types of Health Scores, I am going to first filter the array into scores with the ‘wellbeing’ type.To do this simply add the following line after retrieving the score data:
javascript
const wellbeingScores = inferences?.filter(s => s.type === 'wellbeing') || [];
We then need to convert our welling score array into an array that can be passed into our bar chart.
I am going to use
react-native-gifted-charts
, to keep it simple we only need to pass an array containing a value and a label.For the value we are going to use the score value field, we will also multiply this by 100 to get a percentage value as the score values come back as a number between 0 and 1.
For the label, I am going to use
date-fns
format function to convert the date in a short hand day.Because we want to ensure we show each day in our date range, we need to loop over our
days
array we created earlier, find the score in our score array from the same day and return and object with a value and label.I’m going to create a helper function to do just this, place this function in the render function of your App.tsx file:
javascript
const createChartData = (scores: SahhaScore[]) => days.map(date => { const scoreForDate = scores.find(s => isSameDay(s.createdAt, date)); const value = (scoreForDate?.score || 0) * 100; return {value, label: format(date, 'E')}; });
We then need to create a useState variable to store our chartData array, add the following line to the top of your
App.tsx
file:javascript
const [chartData, setChartData] = useState<BarChartPropsType['data']>([]);
For type safety we are using the
BarChartPropsType
fromreact-native-gifted-charts
and extracting thedata
field from it.We can now update our
useEffect
to transform the data and update ourchartData
state variable.Your
useEffect
should now look like this:javascript
useEffect(() => { (async () => { try { await configureSahha(); await authenticateSahha('healthy-profile-01'); const {inferences} = await analyzeSahhaDateRange(start, end); const wellbeingScores = inferences?.filter(s => s.type === 'wellbeing') || []; setChartData(createChartData(wellbeingScores)); } catch (e) { console.error(e); } })(); }, []);
Finally we simply need to add the
<BarChart>
component fromreact-native-gifted-charts
and pass thechartData
state variable to thedata
property.javascript
<BarChart data={chartData} />
Full code example
Below is the full code example with a few additional styling tweaks.
javascript
import {eachDayOfInterval, format, isSameDay, subDays} from 'date-fns'; import React, {useEffect, useState} from 'react'; import { SafeAreaView, StatusBar, Text, View, useColorScheme, } from 'react-native'; import Config from 'react-native-config'; import {BarChart, BarChartPropsType} from 'react-native-gifted-charts'; import Sahha, {SahhaEnvironment} from 'sahha-react-native'; type SahhaScore = { id: string; type: string; state: string; score: number; factors: { name: string; value: number; }[]; inputData: string[]; createdAt: string; }; type SahhaAnalyzeResponse = { inferences?: SahhaScore[]; }; const SAHHA_CONFIGURATION_SETTINGS = { environment: SahhaEnvironment.sandbox, }; const configureSahha = () => new Promise((resolve, reject) => Sahha.configure( SAHHA_CONFIGURATION_SETTINGS, (error: string, success: boolean) => { if (success) resolve(success); reject(error); }, ), ); const authenticateSahha = (externalId: string) => new Promise((resolve, reject) => Sahha.authenticate( Config.SAHHA_APPLICATION_ID || '', Config.SAHHA_APPLICATION_SECRET || '', externalId, (error, success) => { if (success) resolve(success); reject(error); }, ), ); const analyzeSahhaDateRange = ( startDate: Date, endDate: Date, ): Promise<SahhaAnalyzeResponse> => new Promise((resolve, reject) => Sahha.analyzeDateRange( startDate.getTime(), endDate.getTime(), (error, value) => { try { if (error) throw new Error(error); resolve(JSON.parse(value)); } catch (e) { reject(e); } }, ), ); function App(): React.JSX.Element { const isDarkMode = useColorScheme() === 'dark'; const backgroundColor = isDarkMode ? '#1c1917' : '#fafaf9'; const color = isDarkMode ? '#fafaf9' : '#1c1917'; const end = new Date(); const start = subDays(end, 6); const days = eachDayOfInterval({start, end}); const [chartData, setChartData] = useState<BarChartPropsType['data']>([]); const createChartData = (scores: SahhaScore[]) => days.map(date => { const scoreForDate = scores.find(s => isSameDay(s.createdAt, date)); const value = (scoreForDate?.score || 0) * 100; return {value, label: format(date, 'E')}; }); useEffect(() => { (async () => { try { await configureSahha(); await authenticateSahha('healthy-profile-01'); const {inferences} = await analyzeSahhaDateRange(start, end); const wellbeingScores = inferences?.filter(s => s.type === 'wellbeing') || []; setChartData(createChartData(wellbeingScores)); } catch (e) { console.error(e); } })(); }, []); return ( <SafeAreaView style={{ flex: 1, padding: 16, backgroundColor, }}> <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} backgroundColor={backgroundColor} /> <View style={{flex: 1}}> <Text style={{ fontSize: 16, fontWeight: 'bold', marginBottom: 16, color, }}> Your wellbeing scores </Text> <BarChart data={chartData} barWidth={16} barBorderRadius={4} stepValue={10} maxValue={100} noOfSections={11} frontColor="#0EA5E9" xAxisLabelTextStyle={{color}} yAxisTextStyle={{color}} hideRules xAxisThickness={0} yAxisThickness={0} /> </View> </SafeAreaView> ); } export default App;
And here is the output
Conclusion
In this tutorial, we have successfully created a React Native application that visualizes health-related data using the Sahha SDK. We covered the following key steps:
Setting Up the Project: Initialized a new React Native project and installed the necessary dependencies. Configuring Sahha: Set up the Sahha SDK with your application credentials. Authenticating: Authenticated the user profile to retrieve health data. Retrieving Data: Fetched the wellbeing scores from Sahha's API. Visualizing Data: Displayed the data in a bar chart usingreact-native-gifted-charts
.By following these steps, you can now visualize behavioral health insights within your React Native application, providing valuable feedback and insights to your users.
Feel free to customize and expand upon this foundation to create more complex and interactive visualizations. The integration of Sahha's health data capabilities opens up numerous possibilities for health and wellness applications.