Common components for Ronas IT projects.
- Install dependencies:
npm install
- Start app for local development:
cd apps/example && npx expo start
- Use Expo Go to run mobile version
To publish the package update to NPM, run:
npx nx run lib:nx-release-publish
- Install the package:
npm i @ronas-it/react-native-common-modules
- Import modules to your app and use as described below
At the moment this library contains the following components:
NOTE: Required dependencies:
react-native-safe-area-context
A component for granular control of safe area edges on each screen. The difference from SafeAreaView
in react-native-safe-area-context is that the container adds padding to the elements inside it, rather than to the entire screen, making it more flexible for use.
Props:
edges
: An array indicating which edges of the screen to respect. Possible values are 'top', 'right', 'bottom', 'left'. Defaults to all edges.style
: Custom styles to apply to the view. Note that padding values will be adjusted to respect safe area insets.
Example:
import { AppSafeAreaView } from '@ronas-it/react-native-common-modules/safe-area-view';
<AppSafeAreaView edges={['top', 'bottom']} style={styles.container}>
<Text>Content goes here</Text>
</AppSafeAreaView>;
NOTE: Required dependencies:
@pusher/pusher-websocket-react-native
,pusher-js
,expo-notifications
,expo-router
,expo-constants
,expo-device
,expo-modules-core
Service for integrating Expo push notifications into apps.
Requires setup and backend implementation for sending notifications.
PushNotificationsService
public methods:
-
obtainPushNotificationsToken
- get an Expo token that can be used to send a push notification to the device using Expo's push notifications service. -
pushToken
- getter for retrieving the token if it was already obtained.
Hook, that automatically subscribes the device to receive push notifications when a user becomes authenticated, and unsubscribes when a user becomes non-authenticated. It supports custom subscription and unsubscription logic through provided functions or API configuration. Listens for responses to notifications and executes a callback, if provided, when a notification is interacted with.
Used in the root App
component.
usePushNotifications
hook arguments:
isAuthenticated
(required) - flag, that indicates whether the user is authenticated or not.onNotificationResponse
(optional) - callback when a notification is interacted with.subscribeDevice
(optional) - function for subscribing the device.unsubscribeDevice
(optional) - function for unsubscribing the device.apiConfig
(optional) - API configuration for subscribing and unsubscribing the device (whensubscribeDevice
andunsubscribeDevice
are not provided).apiErrorHandler
(optional) - API error handler for subscribe/unsubscribe functions.getTokenErrorHandler
(optional) - handler for error that occur when attempting to obtain a push notifications token.
Example:
// Somewhere in a root component of your app:
import { usePushNotifications } from '@ronas-it/react-native-common-modules/push-notifications';
...
const authToken = useSelector(authSelectors.token);
...
usePushNotifications({
apiConfig: {
subscribeDeviceUrl: 'https://your-api.com/api/v1/push-notifications/subscribe',
unsubscribeDeviceUrl: 'https://your-api.com/api/v1/push-notifications/unsubscribe',
accessToken: authToken,
},
isAuthenticated: !!authToken,
})
NOTE: By default, when using the
apiConfig
option, the hook sends the Expo push token to your server in the following format:JSON.stringify({ expo_token })
NOTE: Required dependencies:
expo-image-picker
ImagePickerService
gives the application access to the camera and image gallery.
Public methods:
getImage
- initializes the application (camera or gallery) and returns a result containing an image.launchGallery
- launches the gallery application and returns a result containing the selected images.launchCamera
- launches the camera application and returns the taken photo.requestGalleryAccess
- requests the application access to the gallery.requestCameraAccess
- requests the application access to the camera.getFormData
- creates a FormData object with image.
Example
Pick image and send request:
import { imagePickerService, ImagePickerSource } from '@ronas-it/react-native-common-modules/image-picker';
const handlePickImage = async (source: ImagePickerSource) => {
const image = await imagePickerService.getImage(source);
const asset = image?.assets?.[0];
if (!asset) {
return;
}
const data = imagePickerService.getFormData(asset.uri);
// API call
createMedia(data);
};
NOTE: Required dependencies:
@pusher/pusher-websocket-react-native
,pusher-js
WebSocketService
manages WebSocket connections using Pusher and can work in both web and mobile applications.
Doesn't support Expo Go.
It's necessary to install @pusher/pusher-websocket-react-native
for a mobile app and pusher-js for a web app.
Options for WebSocketService
constructor:
apiKey
(required) -APP_KEY
from Pusher Channels Dashboard.cluster
(required) -APP_CLUSTER
from Pusher Channels Dashboard.authURL
(optional) - a URL that returns the authentication signature needed for private channels.useTLS
(optional) - a flag that indicates whether TLS encrypted transport should be used. Default value istrue
.activityTimeout
(optional) - time in milliseconds to ping a server after last message.pongTimeout
(optional) - time in milliseconds to wait a response after a pinging request.
WebSocketService
public methods:
connect
initializes and connects the Pusher client. Optional authorization token is used for secure connections.subscribeToChannel
subscribes to a specified channel and registers an event listener for incoming messages on that channel.unsubscribeFromChannel
removes an event listener and, if there are no listeners for a specified channel, unsubscribes from it.
Example:
import { WebSocketService } from '@ronas-it/react-native-common-modules/websocket';
// Create a service instance
type ChannelName = `private-conversations.${number}` | `private-users.${number}`;
const webSocketService = new WebSocketService<ChannelName>({
apiKey: '1234567890qwertyuiop',
cluster: 'eu',
authURL: 'https://your-api.com/api/v1/broadcasting/auth',
});
// Initialize Pusher, e.g. after an app initialization or successful authorization
await webSocketService.connect('your-auth-token');
// Subscribe to a channel when it's necessary
webSocketService.subscribeToChannel('private-conversations.123', (event) => {
console.log('Received event:', event);
});
// Unsubscribe from a channel, e.g. before an app closing or logging out
webSocketService.unsubscribeFromChannel('private-conversations.123', (event) => {
console.log('Received event:', event);
});
NOTE: Required dependencies:
@reduxjs/toolkit
,reactotron-react-native
,reactotron-react-js
,reactotron-redux
Configures and initializes Reactotron debugger with redux plugin for development purposes.
Install the Reactotron app on your computer for use.
Example:
import { setupReactotron } from '@ronas-it/react-native-common-modules/reactotron';
import { createStoreInitializer } from '@ronas-it/rtkq-entity-api';
import Reactotron from 'reactotron-react-native';
import mmkvPlugin from 'reactotron-react-native-mmkv';
import type { ReactotronReactNative } from 'reactotron-react-native';
import { storage } from './mmkv/storage/instance/location'; // <--- update this to your mmkv instance.
const reactotron = setupReactotron('your-app', [
// You can add an array of Reactotron plugins here
(reactotron) => mmkvPlugin<ReactotronReactNative>({ storage }),
]);
const enhancers = reactotron ? [reactotron.createEnhancer()] : [];
const initStore = createStoreInitializer({
rootReducer: rootReducer as unknown as Reducer<AppState>,
middlewares,
enhancers,
});
NOTE: Required dependencies:
i18n-js
,expo-localization
Provides functions to set language and use translations using i18n-js
Example:
root layout:
import { setLanguage } from '@ronas-it/react-native-common-modules/i18n';
const translations = {
en: {
...require('i18n/example/en.json')
},
fr: {
...require('i18n/example/fr.json')
}
};
const useLanguage = setLanguage(translations, 'en');
interface LanguageContextProps {
language: string;
onLanguageChange?: (language: keyof typeof translations) => void;
}
export const LanguageContext = createContext<LanguageContextProps>({ language: 'en' });
function App(): ReactElement {
return (
<Stack>
<Stack.Screen name='index' />
</Stack>
);
}
export default function RootLayout(): ReactElement | null {
const [language, setLanguage] = useState<keyof typeof translations>('en');
useLanguage(language);
return (
<LanguageContext.Provider value={{ language, onLanguageChange: setLanguage }}>
<App />
</LanguageContext.Provider>
);
}
screen:
import { AppSafeAreaView } from '@ronas-it/react-native-common-modules/safe-area-view';
import { useTranslation } from '@ronas-it/react-native-common-modules/i18n';
import { ReactElement, useContext } from 'react';
import { View, Text, Alert, Pressable } from 'react-native';
import { LanguageContext } from './_layout';
export default function RootScreen(): ReactElement {
const translate = useTranslation('EXAMPLE');
const { language, onLanguageChange } = useContext(LanguageContext);
const onPress = () => Alert.alert(translate('TEXT_PRESSED'));
const handleLanguageChange = (): void => {
onLanguageChange?.(language === 'en' ? 'fr' : 'en');
};
return (
<AppSafeAreaView edges={['bottom']} style={styles.safeAreaContainer}>
<View style={styles.container}>
<Pressable onPress={onPress} hitSlop={10}>
<Text>{translate('BUTTON_PRESS_ME')}</Text>
</Pressable>
<Pressable onPress={handleLanguageChange} hitSlop={10}>
<Text>{translate('BUTTON_LANGUAGE')}</Text>
</Pressable>
</View>
</AppSafeAreaView>
);
}
NOTE: Required dependencies:
@clerk/clerk-expo
,expo-web-browser
,expo-auth-session
Hooks and helpers to create user authentication with Clerk Expo SDK.
Hook, that provides access to essential Clerk methods and objects.
Returned Object:
signUp
- provides access to SignUp object.signIn
- provides access to SignIn object.setActive
- A function that sets the active session.signOut
- A function that signs out the current user.
Hook, that provides functionality to handle user sign-up and sign-in processes using an identifier such as an email, phone number, or username. It supports both OTP (One Time Password) and password-based authentication methods.
Parameters:
method
: Specifies the type of identifier used for authentication (e.g., 'emailAddress', 'phoneNumber', 'username').verifyBy
: Specifies the verification method ('otp' for one-time passwords or 'password').
Returned Object:
startSignUp
: Initiates a new user registration using the specified identifier and verification method.startSignIn
: Initiates authentication of an existing user using the specified identifier and verification method.startAuthorization
: Determines whether to initiate a sign-up or sign-in based on whether the user has been registered previously.verifyCode
: Verifies an OTP code if the verification method is 'otp'.isLoading
: Indicates whether an authentication request is in progress.isVerifying
: Indicates whether an OTP verification is in progress.
Example:
import React, { useState } from 'react';
import { View, TextInput, Button } from 'react-native';
import { useAuthWithIdentifier } from '@ronas-it/react-native-common-modules/clerk';
export const AuthWithIdentifierComponent = () => {
const [identifier, setIdentifier] = useState('');
const [verificationCode, setVerificationCode] = useState('');
const { startSignUp, verifyCode, isLoading, isVerifying } = useAuthWithIdentifier('emailAddress', 'otp');
const handleSignUp = async () => {
await startSignUp({ identifier });
};
const handleVerifyCode = async () => {
const result = await verifyCode({ code: verificationCode });
console.log(result.sessionToken)
};
return (
<View>
<TextInput
placeholder="Enter your email"
value={identifier}
onChangeText={setIdentifier}
keyboardType="email-address"
/>
<TextInput
placeholder="Enter verification code"
value={verificationCode}
onChangeText={setVerificationCode}
/>
<Button onPress={handleSignUp} title="Sign Up" disabled={isLoading || isVerifying} />
<Button onPress={handleVerifyCode} title="Verify code" disabled={isLoading || isVerifying} />
</View>
);
};
Hook provides functionality to handle SSO authentication flows.
Returned Object:
startSSOFlow
: A function to initiate an SSO flow. It takes a strategy, redirectUrl, and optional tokenTemplate as parameters, starting the SSO authentication and returning session information or errors upon completion.isLoading
: A boolean indicating whether an SSO process is currently ongoing.
This hook is a utility that facilitates user authentication using a ticket-based strategy (ticket is a token generated from the Backend API).
Returned Object:
startAuthorization
: A function to initiate authentication with a ticket. It accepts an object with ticket and optional tokenTemplate parameters to kick off the authorization process and returns the session details.isLoading
: A boolean indicating whether the ticket-based authorization process is ongoing.
This hook is a utility for getting session tokens.
Returned Object:
getSessionToken
: A function to retrieve the session token. It takes an optional tokenTemplate parameter to specify a template for the token.
Hook provides functionality to add new email or phone number identifiers to a user's account and verify them using verification codes.
Returned Object:
createIdentifier
: A function to add a new email or phone number identifier to the user's account and prepare it for verification.verifyCode
: A function to verify a code sent to the identifier, completing the verification process.isCreating
: A boolean indicating whether an identifier is currently being added.isVerifying
: A boolean indicating whether a verification code is currently being processed.
Hook provides functionality for managing OTP (One Time Password) verification in user authentication workflows, supporting both sign-up and sign-in processes.
Returned Object:
sendOtpCode
: Sends an OTP code to the user's identifier (email or phone number) based on the specified strategy.verifyCode
: Verifies the OTP code provided by the user, completing the authentication process.isVerifying
: A boolean indicating whether a verification attempt is currently in progress.
Hook provides methods to handle password reset functionality through email or phone-based OTP.
Returned Object:
startResetPassword
: A function to initiate the password reset process by sending a verification code to the user's email or phone number.resetPassword
: A function to reset the user's password by verifying the code and setting a new password.isCodeSending
: A boolean indicating if the verification code is being sent.isResetting
: A boolean indicating if the password is being reset.