Comprehensive Guide to Choosing Between `useEffect` and `useFocusEffect` in React & React Native

React and React Native offer powerful hooks to manage the lifecycle of your components, with useEffect and useFocusEffect being two of the most commonly used. While both are essential for managing side effects, their purposes and use cases differ significantly. Understanding when to use each can help you write more efficient, maintainable, and performant code. In this blog, we’ll dive deep into the differences between useEffect and useFocusEffect and explore when to use them.
What is useEffect?
The useEffect hook in React and React Native is a foundational tool for managing side effects in functional components. It’s triggered after the render phase and can be used for various purposes like fetching data, subscribing to events, or updating the DOM (or equivalent in React Native).
Syntax:
useEffect(() => {
// Perform side effect
return () => {
// Cleanup if necessary
};
}, [dependencies]);
Common Use Cases:
Data Fetching: Fetching data when a component mounts.
Event Listeners: Adding or removing event listeners, such as for network changes or keyboard visibility.
Timers: Managing intervals or timeouts.
Reacting to Prop or State Changes: Running specific logic whenever props or state values change.
Example:
import React, { useEffect, useState } from 'react';
import { View, Text } from 'react-native';
const ExampleComponent = () => {
const [data, setData] = useState(null);
useEffect(() => {
// Fetch data when component mounts
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []); // Empty dependency array ensures this runs only on mount
return (
<View>
<Text>{data ? JSON.stringify(data) : 'Loading...'}</Text>
</View>
);
};
export default ExampleComponent;
What is useFocusEffect?
The useFocusEffect hook is part of React Navigation and is used to run side effects whenever a screen gains or loses focus. Unlike useEffect, it integrates closely with navigation lifecycle events.
Syntax:
useFocusEffect(
useCallback(() => {
// Perform side effect
return () => {
// Cleanup if necessary
};
}, [dependencies])
);
Common Use Cases:
Refreshing Data: Re-fetching or refreshing data when a screen is revisited.
Event Listeners: Adding listeners that should only be active when the screen is focused (e.g., hardware back button handling).
Resetting States: Clearing or resetting certain states when the screen comes into view.
Example:
import React, { useState, useCallback } from 'react';
import { View, Text } from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
const FocusedScreen = () => {
const [message, setMessage] = useState('Welcome!');
useFocusEffect(
useCallback(() => {
// Triggered when screen is focused
const interval = setInterval(() => {
console.log('Screen is focused');
}, 1000);
return () => {
// Cleanup when screen loses focus
clearInterval(interval);
};
}, [])
);
return (
<View>
<Text>{message}</Text>
</View>
);
};
export default FocusedScreen;
Key Differences Between useEffect and useFocusEffect
Feature useEffect useFocusEffect Trigger Timing Runs after every render or when dependencies change. Runs only when the screen gains or loses focus. Dependency on Navigation Independent of navigation. Requires React Navigation context. Common Use Case Data fetching, state updates, and global side effects. Screen-specific tasks like refreshing data. Cleanup Cleanup occurs on unmount or dependency change. Cleanup occurs when the screen loses focus.
When to Use useEffect
Use useEffect when your side effect is:
Independent of Navigation: If your logic is tied to the lifecycle of the component and not the navigation lifecycle.
Global or Persistent: For tasks that don’t depend on whether a screen is in focus, like subscribing to global events or managing intervals.
Prop or State Dependent: When the logic should re-run due to changes in props or local state.
Example Use Cases:
Fetching global configuration data.
Subscribing to device orientation changes.
Starting and cleaning up background tasks like timers.
When to Use useFocusEffect
Use useFocusEffect when your side effect:
Depends on Navigation State: If the logic should only run when the screen is active or focused.
Screen-Specific Tasks: For actions like reloading data or starting listeners that are tied to a specific screen.
Improves Performance: Avoid running unnecessary logic when the screen is not visible, reducing resource consumption.
Example Use Cases:
Fetching user data when navigating back to a profile screen.
Resetting a form or clearing input fields when a screen regains focus.
Listening for hardware back button presses only when a screen is active.
Combining useEffect and useFocusEffect
In some scenarios, you may need both useEffect and useFocusEffect. For example, you might use useEffect to perform one-time setup logic and useFocusEffect to handle navigation-specific tasks.
Example:
import React, { useEffect, useCallback, useState } from 'react';
import { View, Text } from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
const CombinedExample = () => {
const [data, setData] = useState(null);
// Fetch data on initial render
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
// Refresh data when screen is focused
useFocusEffect(
useCallback(() => {
console.log('Screen is focused');
return () => console.log('Screen lost focus');
}, [])
);
return (
<View>
<Text>{data ? JSON.stringify(data) : 'Loading...'}</Text>
</View>
);
};
export default CombinedExample;
Conclusion
useEffect and useFocusEffect are both indispensable tools for managing side effects in React and React Native. By understanding their differences and use cases, you can make more informed decisions about which hook to use, resulting in cleaner and more efficient code. Use useEffect for component lifecycle-related tasks and useFocusEffect for navigation lifecycle-related tasks. Mastering these hooks will make your apps more robust and maintainable.




