“Best Use Cases for State Management Approaches: A Developer’s Guide to Seamless App Control”

Covenant Ifeoluwa
Our Internship Journey
4 min readAug 11, 2023

In the previous section, we delved into the significance of state management in React Native applications and briefly introduced several popular state management approaches and libraries. Now, let’s take a closer look at some of these examples and explore their best use cases.

First, we will talk about the React Context API

The React Context API stands out as an excellent solution for managing states across disconnected components within a React application. It effectively addresses the challenge of prop-drilling, which can arise when passing data through multiple layers of components. This API simplifies the process by allowing components to access the required data directly from a shared context, enhancing code organization and reducing complexity. This article is meant to provide detailed documentation and demonstration of how State Management Works in React Native. I would like to take each case one after the other in each article.

React Context is an ideal choice for state management in the following scenarios:

Shared Data: When you have data that needs to be accessed by multiple components across different levels of the component tree. Instead of passing props down the tree, you can provide the data using a context and consume it where needed. Here is a detailed example with Expo Version 49.0.6. If you will like to check how to set up your expo app click here:

Step 1: Create a new file named UserContext.js for defining the context and providing the shared data:

import { createContext, useContext, useState } from 'react';

export const UserContext = createContext();

export const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);

return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};

export const useUser = () => useContext(UserContext);

Step 2: Create a LoginScreen.js component with a login form:

import { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet, Image, TouchableOpacity } from 'react-native';
import { useUser } from '../Context/UserContext';

const LoginScreen = ({navigation}) => {
const { setUser } = useUser();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');

const handleLogin = () => {
// Perform login validation logic here
// For simplicity, let's assume successful login
setUser({ username });
navigation.navigate('UserProfile');
};

return (
<View style={styles.container}>
<View style={styles.logoBox}>
<Image
source={require("../assets/icon.png")}
style={styles.logo}
/>
<Text style={styles.loginText}>CovenantCodes</Text>
</View>
<TextInput
placeholder="Username"
style={styles.textInput}
value={username}
onChangeText={setUsername}
/>
<TextInput
placeholder="Password"
secureTextEntry
style={styles.textInput}
value={password}
onChangeText={setPassword}
/>

<TouchableOpacity style={styles.buttonContainer}
onPress={handleLogin}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
</View>
);
}

const styles = StyleSheet.create({
container:{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},

logoBox:{
width: "30%",
padding: 5,
alignItems: "center",
marginBottom: 12
},

logo:{
width: 60,
height: 100
},

loginText:{
fontSize:16,
fontWeight:"bold",
width: "100%",
marginTop: 5,
},

textInput:{
width: "80%",
backgroundColor: "white",
borderColor: "gray",
padding: 10,
marginTop: 10,
borderRadius: 10,
shadowColor: "#000000",
shadowOffset: {
width: 0,
height: 5,
},
shadowOpacity: 0.36,
shadowRadius: 6.68,
elevation: 5
},

buttonContainer:{
width: "80%",
padding: 15,
marginHorizontal: 20,
marginTop: 15,
backgroundColor: "orange",
borderRadius: 10,
shadowColor: "#000000",
shadowOffset: {
width: 0,
height: 5,
},
shadowOpacity: 0.36,
shadowRadius: 6.68,
elevation: 10
},

buttonText: {
textAlign: "center",
color: "white",
fontSize: 15
},
})

export default LoginScreen;

Step 3: Create a UserProfileScreen.js component to display the user's profile information:

// UserProfile.js
import { useContext } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { useUser } from './Context/UserContext.js';

const UserProfileScreen = ()=> {
const { user } = useUser();

return (
<View style={styles.container}>
{user ? (
<Text>Welcome, {user.username}!</Text>
) : (
<Text>Please log in to see user info.</Text>
)}
</View>
);
}

const styles = StyleSheet.create({
container:{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})

export default UserProfileScreen;

Step 4: Create a StackNavigator.js file to set up navigation between screens:

import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import LoginScreen from '../Screens/LoginScreen';
import UserProfileScreen from '../UserProfile';

const Stack = createStackNavigator();

const StackNavigator = ()=> {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Login">
<Stack.Screen
name="Login"
component={LoginScreen}
options={{
headerShown: false
}}

/>
<Stack.Screen
name="UserProfile"
component={UserProfileScreen}
options={{
headerShown: false
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}

export default StackNavigator;

Step 5: Finally, in your main App.js file, use the UserProvider to wrap the StackNavigator:

import { UserProvider } from './Context/UserContext';
import StackNavigator from './navigator/StackNavigator';

const App =()=> {
return (
<UserProvider>
<StackNavigator />
</UserProvider>
);
}

export default App;

You can find the full source code in this GitHub repository

Here is a demo of the app

Next, we will be looking at an example of when you need to maintain a Global State

--

--