Step 1: Creating the Context (BaseUrlContext)
The BaseUrlContext provides a central location where global settings like the baseUrl and dial_code can be stored and accessed throughout the app.
import React, { createContext, useState, useContext, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
// Create context
const BaseUrlContext = createContext();
// Custom hook to use the context
export const useBaseUrl = () => {
return useContext(BaseUrlContext);
};
createContext(): This creates the context object for global state management. In this case, it's named BaseUrlContext.
useBaseUrl: A custom hook to access the BaseUrlContext. This makes it easier to access the context in different components without having to manually use useContext each time.
Step 2: Setting up the Context Provider (BaseUrlProvider)
The BaseUrlProvider component will wrap the app and manage the state for baseUrl and dial_code globally. It also provides functions to update these values and persist them using AsyncStorage.
import React, { createContext, useState, useContext, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
const BaseUrlContext = createContext();
export const useBaseUrl = () => {
return useContext(BaseUrlContext);
};
export const BaseUrlProvider = ({ children }) => {
const [baseUrl, setBaseUrl] = useState('');
const [dialCode, setDialCode] = useState(''); // State to store dial_code
const [otp, setOtp] = useState(''); // State to store OTP
const [phone, setPhone] = useState(''); // State to store phone number
useEffect(() => {
const fetchBaseUrl = async () => {
const storedBaseUrl = await AsyncStorage.getItem('baseUrl');
const storedDialCode = await AsyncStorage.getItem('dialCode'); // Fetch dial_code from AsyncStorage
const storedOtp = await AsyncStorage.getItem('otp'); // Fetch OTP from AsyncStorage
const storedPhone = await AsyncStorage.getItem('phone'); // Fetch phone number from AsyncStorage
if (storedBaseUrl) {
setBaseUrl(storedBaseUrl);
}
if (storedDialCode) {
setDialCode(storedDialCode);
}
if (storedOtp) {
setOtp(storedOtp); // Set OTP in state from AsyncStorage
}
if (storedPhone) {
setPhone(storedPhone); // Set phone number in state from AsyncStorage
}
};
fetchBaseUrl();
}, []);
// Function to set a new base URL and remove previous values
const setNewBaseUrl = async (url) => {
await AsyncStorage.removeItem('otp'); // Remove OTP when setting a new base URL
await AsyncStorage.removeItem('phone'); // Remove phone number when setting a new base URL
await AsyncStorage.removeItem('dialcode'); // Remove phone number when setting a new base URL
await AsyncStorage.setItem('baseUrl', url);
setBaseUrl(url);
};
// Function to set a new dial code and remove previous values
const setNewDialcode = async (dialcode) => {
await AsyncStorage.removeItem('otp'); // Remove OTP when setting a new dial code
await AsyncStorage.removeItem('phone'); // Remove phone number when setting a new dial code
await AsyncStorage.setItem('dialCode', dialcode); // Save dial_code to AsyncStorage
setDialCode(dialcode); // Update dial_code in context
};
// Function to set a new OTP and remove previous phone number
const setNewOtp = async (otp) => {
await AsyncStorage.setItem('otp', otp); // Save OTP to AsyncStorage
setOtp(otp); // Update OTP in context
console.log('OTP set in context:', otp);
};
// Function to set a new phone number and remove OTP
const setNewPhone = async (phone) => {
await AsyncStorage.setItem('phone', phone); // Save phone to AsyncStorage
setPhone(phone); // Update phone in context
};
return (
<BaseUrlContext.Provider value={{ baseUrl, dialCode, otp, phone, setNewBaseUrl, setNewDialcode, setNewOtp, setNewPhone }}>
{children}
</BaseUrlContext.Provider>
);
};
useState: React's state management hook to store baseUrl and dialCode globally.
useEffect: On app load, this hook fetches the stored values from AsyncStorage and sets them into the context state. This ensures the app retains settings even after a restart.
setNewBaseUrl and setNewDialcode: These functions are responsible for updating the baseUrl and dial_code both in the context and in AsyncStorage. AsyncStorage.setItem is used to persist these settings.
Step 3: Wrapping the App with the BaseUrlProvider
To make the context accessible throughout the app, we need to wrap the app with the BaseUrlProvider component. This ensures that any component inside the BaseUrlProvider can access and update the global settings.
export default function App() {
return (
<BaseUrlProvider> {/* Wrap the app with BaseUrlProvider */}
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="CountrySelection"
component={CountrySelectionPage}
options={{ title: 'Select Country' }}
/>
<Stack.Screen
name="Main"
component={MainDrawerNavigator}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
</BaseUrlProvider>
);
}
BaseUrlProvider: By wrapping the app with BaseUrlProvider, the global settings (baseUrl, dial_code) are now available in any component within the app using the useBaseUrl hook.
Step 4: Accessing and Updating the Global Settings in the Parent Component
In the parent component, you can access and update the dial_code by using the useBaseUrl hook. The example shows how to update the dial_code when a user selects a country from a modal (CountrySelectModal).
import { useBaseUrl } from '../contexts/BaseUrlContext'; // Import the useBaseUrl hook
const { setNewDialcode } = useBaseUrl(); // Get the function to update the dial_code
const handleCountrySelect = async (country) => {
try {
setSelectedCountry(country.name); // Store only the country name
setIsPhoneEnabled(true); // Enable the phone input after selecting a country
setIsModalVisible(false); // Close the modal after selection
await setNewDialcode(country.dial_code); // Save the dial_code globally using context
console.log('Country and dial_code saved successfully');
} catch (error) {
console.error('Error saving country data:', error);
}
};
setNewDialcode: This function is called to update the dial_code in the global state via the BaseUrlContext.
AsyncStorage: The dial code is also saved in AsyncStorage so that it persists across app restarts.
==========================OR============================
we can set it in controller useMotoshareViewModel
await setNewOtp(otp); // Save OTP to context and AsyncStorage
const sendOtp = async (phoneNumber) => {
//setIsLoading(true); // Start loading state
const api = new MotoshareAPI(baseUrl); // Pass baseUrl from context to MotoshareAPI
console.log("OTP sendOtp ing");
try {
// Call the API to send OTP
const response = await api.sendOtp({ phone: phoneNumber }); // Assuming POST request with phone parameter
if (response && response.success) {
console.log("OTP sent successfully");
console.log(phoneNumber);
const otp = response.otp.toString(); // Ensure OTP is a string
await setNewOtp(otp); // Save OTP to context and AsyncStorage
await setNewPhone(phoneNumber); // Save phone number in context and AsyncStorage
} else {
throw new Error("Failed to send OTP");
}
} catch (error) {
console.error("Error sending OTP:", error);
setMessage("Failed to send OTP");
} finally {
setIsLoading(false); // Stop loading state
}
};
Step 5: Rendering the Country Selection Modal and Passing Data
The CountrySelectModal component will render a list of countries, and when a user selects a country, it will trigger the handleCountrySelect function from the parent component to update the global state.
<CountrySelectModal
isModalVisible={isModalVisible}
setIsModalVisible={setIsModalVisible}
countries={countries}
handleCountrySelect={handleCountrySelect}
isLoading={isLoading}
searchTerm={searchTerm}
handleSearchChange={handleSearchChange}
filteredCountries={filteredCountries}
/>
Step 6: Using the Global Settings in Other Parts of the App
Anywhere in your app, you can now access the baseUrl and dial_code using the useBaseUrl hook.
Example:
const { baseUrl, dialCode } = useBaseUrl();
console.log('Selected Dial Code:', dialCode); // Access the dial_code from the context
const { setNewDialcode, otp,phone} = useBaseUrl(); // Get the function to update the dial_code and OTP from context
const handleVerifyOtp = async () => {
// Compare entered OTP with stored OTP in context
console.log("OTP inside!");
console.log(otp);
console.log(inputOtp);
if (inputOtp == otp) {
console.log("OTP Verified Successfully!");
console.log(otp);
console.log("Sending OTP to phone:", phoneNumber); // Add this log
// await verifyOtp(otp,phone); // Pass the phone number to send OTP
} else {
console.log("Invalid OTP!");
Alert.alert("Error", "Invalid OTP entered.");
}
};
This allows you to use the selected country’s dial_code globally, without passing it down through props.
Top comments (0)