The Context API in React Native allows for global state management, but when dealing with complex state updates or performance optimizations, useCallback and useMemo become crucial. They help prevent unnecessary re-renders and optimize performance.
Why Use useCallback and useMemo?
πΉ useCallback ensures functions donβt get re-created unnecessarily.
πΉ useMemo prevents recalculations of derived state when dependencies haven't changed.
πΉ Both improve performance when passing values through Context.
1. Implementing Context API
Step 1: Create a Context
import React, { createContext, useState, useCallback, useMemo } from "react";
export const AppContext = createContext();
Step 2: Create a Provider with useCallback and useMemo
const AppProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState("light");
return (
<AppContext.Provider value={{ user, setUser, theme, setTheme }}>
{children}
</AppContext.Provider>
);
};
export default AppProvider;
or
const AppProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState("light");
// useCallback to prevent function recreation
const toggleTheme = useCallback(() => {
setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
}, []);
const loginUser = useCallback(() => {
setUser("John Doe");
}, []);
// useMemo to optimize the value object
const contextValue = useMemo(() => ({
user,
theme,
toggleTheme,
loginUser,
}), [user, theme, toggleTheme, loginUser]);
return (
<AppContext.Provider value={contextValue}>
{children}
</AppContext.Provider>
);
};
export default AppProvider;
Optimizations:
-
toggleThemeandloginUseruseuseCallbackto avoid unnecessary re-creations. -
contextValueusesuseMemoto ensure it only changes when dependencies update.
Step 3: Wrap the App with the Provider
import React from "react";
import { View, Text } from "react-native";
import AppProvider from "./AppProvider";
import HomeScreen from "./HomeScreen";
const App = () => {
return (
<AppProvider>
<HomeScreen />
</AppProvider>
);
};
export default App;
Step 4: Consume Context in a Component
import React, { useContext } from "react";
import { View, Text, Button } from "react-native";
import { AppContext } from "./AppProvider";
const HomeScreen = () => {
const { user, theme, toggleTheme, loginUser } = useContext(AppContext);
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Current User: {user || "Guest"}</Text>
<Text>Theme: {theme}</Text>
<Button title="Login" onPress={loginUser} />
<Button title="Toggle Theme" onPress={toggleTheme} />
</View>
);
};
export default HomeScreen;
Why This is Optimized?
π Prevents unnecessary re-renders when passing functions (useCallback).
π Prevents unnecessary re-creation of objects (useMemo).
π Improves performance when using Context API in larger apps.
When to Use useCallback and useMemo?
β
Use useCallback when passing functions to child components to prevent re-creation.
β
Use useMemo when computing derived values that are expensive to recalculate.
When to Use Context API in React Native?
β
When managing global state (authentication, themes, language preferences).
β
When passing data deeply into the component tree.
β
When you need a simple state management solution.
β Avoid using it for frequently changing state (like animations or high-frequency updates).
β Not ideal for complex state management (consider Redux/Zustand in such cases).
Final Thoughts
- Context API is great for global state, and adding
useCallbackanduseMemooptimizes it. - For complex state management, consider Redux, Zustand, or Recoil for better scalability.
Top comments (0)