Are you struggling with performance issues in your React application? Discover how to use useCallback and useEffect to solve common problems and build better apps.
https://www.frontendmag.com/tutorials/usecallback-vs-useeffect-react-hooks/
Best Angular 17 Classroom & Online training - Naresh IT
React Hooks Demystified: How to Effectively Use useCallback and useEffect
1. Home Tutorials useCallbackvsuseEffect: Exploringthe DifferencesBetweenTwo ReactHooks
useCallback vs useEffect: Exploring the
Differences Between Two React Hooks
AUTHOR
Tien Nguyen
DATE
March11, 2023
CATEGORY
Tutorials
Share
Hey there! If you’ve been working with React for a while, you’ve probably come across React hooks,
which were introduced in React 16.8. Hooks allow you to reuse stateful logic in functional components,
making them more powerful and flexible. In this article, we’re going to dive deep into two of the most
commonly used React hooks: vs .
But first, let’s talk about why hooks are so important in React. In traditional class components, managing
stateful logic was often complex and required a lot of boilerplate code. Hooks provide a much simpler
and more concise way to handle stateful logic, making it easier to write and maintain code. Hooks have
become a critical feature of modern React development, and understanding how to use them is
essential for building high-quality, performant React applications.
Now, let’s take a look at and . In short, is a hook that allows
you to memoize a function and pass it to child components without causing unnecessary re-renders. On
the other hand, is a hook that allows you to perform side effects, such as retrieving data
from an API, updating the DOM, or subscribing to events.
The objective of this article is to help you understand the differences between and
, and to provide you with the knowledge to choose the right hook for your use case. By the
end of this article, you’ll have a solid understanding of when to use each hook and how to avoid common
mistakes and pitfalls when using them. So, let’s dive in!
useCallback useEffect
useCallback useEffect useCallback
useEffect
useCallback
useEffect
Recent posts
14 Best Books To Learn
Javascript (ES6+) In 2023
From Beginner To
Advanced
March 8,2023
Is Front End Development
Dying? Why It’s Here To
Stay, Despite What You’re
Heard
March 5,2023
A List Of Careers In Web
Development: Exploring
Different Paths
March 2,2023
SolidJS vs Svelte: The
Ultimate Comparison of
Two Innovative Web
Frameworks
February 25,2023
Material UI vs Tailwind
CSS: Which is Better for
React Development?
February 21,2023
HOME TUTORIALS TIPS INSIGHTS CAREER RESOURCES
2. What is the useCallback Hook?
is a React hook that allows you to memoize a function and pass it to child components
without causing unnecessary re-renders. Memoization is a method used to optimize expensive
functions by caching their results. This means that if the function is called again with the same inputs,
the cached result is returned instead of recomputing the function.
takes two arguments:
the first is the functionthatyouwanttomemoize;
and the second is anarray ofdependencies.
The dependencies array is used to determine when the function should be re-memoized. If any of the
dependencies change, the function is re-memoized and a new reference is returned.
You should use when you need to pass a function down to a child component as a prop,
but the function may be expensive to compute or causes unnecessary re-renders. By memoizing the
function with , you can ensure that the function is only recomputed when the
dependencies change, rather than every time the parent component renders.
For instance, suppose you have a parent component that renders a list of child components. Each child
component needs to call a function passed down from the parent. Without memoization, every time the
parent component renders, a new reference to the function is created, causing unnecessary re-renders
of the child components. By using to memoize the function, the reference to the
function is only recreated when the dependencies change, reducing the number of re-renders and
improving performance.
Here’s a code example of how to use to memoize a function that’s used in a child
component:
Tableof Contents
1. What is the useCallback Hook?
2. What is the useEffect Hook?
3. Differences between useCallback vs useEffect
4. Common Mistakes and Pitfalls to Avoid when Using These Hooks
5. Performance Implications of Using useCallback vs useEffect
6. Typical Examples of when to Use One Hook over the Other
7. How to Test Components that Use useCallback and useEffect
8. Final Thoughts
9. FAQs
useCallback
useCallback
useCallback
useCallback
useCallback
useCallback
1. import React, { useState, useCallback } from 'react'
2. import TodoItem from './TodoItem'
3.
4. function TodoList() {
5. const [todos, setTodos] = useState([
6. { id: 1, text: 'Call the bank', completed: false },
7. { id: 2, text: 'Schedule a dentist appointment', completed: true },
8. { id: 3, text: 'Clean the garage', completed: false },
9. ])
10.
11. const handleComplete = useCallback(
12. (id) => {
13. setTodos((prevTodos) =>
14. prevTodos.map((todo) =>
15. todo.id === id ? { ...todo, completed: !todo.completed } : todo
16. )
17. )
18. },
19. [setTodos]
20. )
21.
22. return (
23. <div>
24.
3. In this example, the component renders a list of child components, each of
which has a checkbox to mark the todo as completed. When the checkbox is clicked, the
function passed down from the parent component is called to update the status of the
todo.
Without memoization, the function would be recreated every time the parent component
re-renders, even if its dependencies (in this case, just the function) have not changed. By
wrapping the function in , the function reference is only recreated when the
function changes, reducing unnecessary re-renders of the child components and improving
performance.
What is the useEffect Hook?
The hook is another important hook in React that allows you to perform side effects in
function components. Side effects are anything that affects the state of the application outside of the
component itself.
Like , the hook also takes two parameters:
The first parameter is the effectfunction that should be executed. The effect function can be
synchronous or asynchronous and should not return anything.
The second parameter is anoptional array ofdependencies. This parameter is used to tell React
when to execute the effect function. If the dependencies are not provided, the effect function will be
executed after every render. If the dependencies are provided, the effect function will be executed
only when one of the dependencies has changed.
However, unlike , the hook returns nothing.
You should use the hook whenever you need to perform a side effect in your component.
This could include:
Fetching data from an API
Updating the document title
{todos.map((todo) => (
25. <TodoItem key={todo.id} todo={todo} onComplete={handleComplete} />
26. ))}
27. </div>
28. )
29. }
30.
31. export default TodoList
TodoList TodoItem
onComplete
completed
onComplete
setTodos
useCallback setTodos
useEffect
useEffect useEffect
useCallback useEffect
useEffect
4. Manipulating the DOM
Setting up subscriptions
By default, functions defined in function components are called on every render, so if you perform side
effects directly in your component function, they will run on every render, which could result in poor
performance and unexpected behavior.
The hook solves this problem by allowing you to specify which values your function
depends on, and only re-running it when those values change. This makes it easier to write side-
effecting code that only runs when it needs to.
Here’s an example of using the hook to fetch data from an API:
In this code, is used to fetch data from an API endpoint and update the state of the
variable with the retrieved data using the function.
The hook is called only once on the component mount, as there are no dependencies
passed in the dependency array. This ensures that the is performed only once, when the
component mounts, and not on every re-render. This example demonstrates how can be
used to retrieve data from an external API and set it into the state.
Below is a different version of the above code in which has a dependency:
useEffect
useEffect
1. import React, { useState, useEffect } from 'react'
2.
3. function UsersList() {
4. const [users, setUsers] = useState([])
5.
6. useEffect(() => {
7. fetch('https://jsonplaceholder.typicode.com/users')
8. .then((response) => response.json())
9. .then((data) => setUsers(data))
10. .catch((error) => console.log(error))
11. }, [])
12.
13. return (
14. <div>
15. <h2>Users:</h2>
16. <ul>
17. {users.map((user) => (
18. <li key={user.id}>{user.name}</li>
19. ))}
20. </ul>
21. </div>
22. )
23. }
24.
25. export default UsersList
useEffect
users setUsers
useEffect
fetch
useEffect
useEffect
1. import React, { useState, useEffect } from 'react'
2.
3. function UsersList() {
4. const [users, setUsers] = useState([])
5. const [isLoading, setIsLoading] = useState(true)
5. In this code, the hook has a dependency of , which is initially set to .
When the component first mounts, the effect is triggered and fetches data from the API. When the data
is received, the state is updated and is set to .
When the “Refresh” button is clicked, the function is called and sets
back to , which triggers the hook again and fetches new data from the API.
By using only one dependency in the hook, we ensure that the effect is only triggered
when the dependency value changes, and not on every re-render of the component.
Differences between useCallback vs useEffect
While and hooks share some similarities, they serve different purposes and
have different use cases.
6.
7. useEffect(() => {
8. fetch('https://jsonplaceholder.typicode.com/users')
9. .then((response) => response.json())
10. .then((data) => {
11. setUsers(data)
12. setIsLoading(false)
13. })
14. .catch((error) => console.log(error))
15. }, [isLoading])
16.
17. const handleRefresh = () => {
18. setIsLoading(true)
19. }
20.
21. return (
22. <div>
23. <h2>Users:</h2>
24. {isLoading ? (
25. <p>Loading users...</p>
26. ) : (
27. <>
28. <button onClick={handleRefresh}>Refresh</button>
29. <ul>
30. {users.map((user) => (
31. <li key={user.id}>{user.name}</li>
32. ))}
33. </ul>
34. </>
35. )}
36. </div>
37. )
38. }
39.
40. export default UsersList
useEffect isLoading true
users isLoading false
handleRefresh isLoading
true useEffect
useEffect
useCallback useEffect
6. The main difference between and is that is used to
memoize a function instance, while is used to manage side effects.
When a function is memoized with , it is only recreated when the dependencies passed
to the hook change. This can improve performance in cases where a function is passed down as a prop
to a child component, as it ensures that the child component only re-renders when necessary.
On the other hand, is used to manage side effects, such as fetching data, updating the
DOM, or setting up event listeners. It allows you to perform these actions after the component has been
rendered, and can also clean up any resources that were used by the side effect.
In general, should be used when you need to memoize a function instance to optimize
performance, while should be used when you need to manage side effects.
Common Mistakes and Pitfalls to Avoid when Using These
Hooks
While and hooks offer numerous benefits, there are also common mistakes
and pitfalls that developers need to be aware of.
One of the most common mistakes developers make is overusing or misusing these hooks. Overusing
can lead to excessive memory usage while misusing can result in a
significant impact on performance. It’s essential to use these hooks only when necessary and
understand how they work to avoid any unintended consequences.
The dependency array is a crucial aspect of both and hooks. It specifies
the variables that trigger re-renders when they change. One common mistake is not specifying the
dependency array, resulting in infinite re-renders. Another mistake is not including all the necessary
dependencies, leading to stale data or missed updates. It’s crucial to understand how the dependency
array works and ensure that all necessary dependencies are included.
Closures can also cause issues when using and . When using closures, the
variables’ values are captured at the time the closure is created, resulting in stale data. This can cause
unexpected behavior and bugs. An effective way to avoid this is by using the hook to store
variables that should persist between renders.
By avoiding these common mistakes and pitfalls, you can make the most out of these hooks while
ensuring your applications’ optimal performance and stability.
Performance Implications of Using useCallback vs useEffect
When using React hooks, it’s important to consider the performance implications of your code. While
both and can optimize performance in certain scenarios, there are some
differences to keep in mind.
can help to prevent unnecessary re-renders by memoizing a function and only
updating it if its dependencies change. This can be especially helpful for functions that are passed
down as props to child components. By using to memoize the function, you can prevent
unnecessary re-renders of those child components.
useCallback useEffect useCallback
useEffect
useCallback
useEffect
useCallback
useEffect
useCallback useEffect
useCallback useEffect
useCallback useEffect
useCallback useEffect
useRef
useCallback useEffect
useCallback
useCallback
7. On the other hand, is used to handle side effects in your components. However, it’s crucial
to be aware of how often is called, as it can lead to unnecessary re-renders and potentially
impact performance.
In general, it’s important to strike a balance between using these hooks to optimize performance and
avoiding overuse or misuse that can lead to performance issues. As with any optimization technique, it’s
important to test and measure the impact of using and in your specific use
cases.
In addition to using these hooks correctly, there are other performance considerations to keep in mind,
such as optimizing the size and complexity of your components, minimizing unnecessary re-renders,
and avoiding excessive state updates.
By keeping these performance considerations in mind and using and
judiciously, you can build React components that are both efficient and effective.
Typical Examples of when to Use One Hook over the Other
As we have discussed, both and hooks serve different purposes in React
and can be used in various scenarios. Here are some typical examples of when to use one hook over the
other:
WhentoUse useCallback WhentoUse useEffect
Dealing with heavy computation or rendering
processes that can slow down the application’s
performance
Dealing with side effects such as fetching data,
setting up subscriptions, or manipulating the
DOM
Passing a function to a child component as a prop
Cleaning up after a component when it
unmounts
Memoizing values other than functions Responding to changes in state or props
By understanding the differences between and and applying them in
appropriate scenarios, you can optimize your React application’s performance and maintainability.
How to Test Components that Use useCallback and useEffect
Testing components that use hooks like and can be challenging, especially
when dealing with asynchronous operations or complex state management. Here are some tips to make
testing these components easier:
Use mockinglibraries: Jest and Enzyme are popular testing libraries that provide useful utilities for
mocking functions and components. You can use them to mock the functions passed to
and hooks.
Testthe effectsofhooks: Use Enzyme’s function to test the effects of hooks in your
components. For example, you can test whether the hook was called, and whether it
updated the component’s state correctly.
Use snapshottesting: Snapshot testing is a quick way to ensure that the output of a component
does not change unexpectedly. You can use snapshot testing with components that use hooks to
ensure that the output remains the same, even if the internal implementation changes.
Testedge cases: When testing components that use hooks, it’s important to test edge cases such as
empty or null values. These edge cases can reveal potential bugs that might not be visible during
normal usage.
Testwithdifferentinputs: When testing components that use hooks, it’s essential to test them with
different inputs. You can use Enzyme’s function to pass different props to the component
and see how it behaves.
useEffect
useEffect
useCallback useEffect
useCallback useEffect
useCallback useEffect
useCallback useEffect
useCallback useEffect
useCallback useEffect
mount
useEffect
shallow
8. By following these tips, you can write tests for components that use hooks like and
and ensure that they work as expected.
Final Thoughts
In conclusion, and are two important React hooks that have distinct use
cases. While is used to memoize a function and optimize performance, is
used to handle side effects and perform actions after the component has been rendered.
It’s essential to understand the differences between the two hooks and use them appropriately to avoid
common mistakes and improve the performance of your React application. You should also be aware of
potential pitfalls, such as dependency array gotchas and stale data caused by closures.
Testing components that use and is crucial to ensure their proper
functionality. By using tools like Jest and Enzyme, you can write tests to verify that your components
are working as intended.
Overall, both hooks are powerful tools that can help you build efficient and effective React applications.
By understanding their differences and use cases, you can leverage them to their full potential and
create better user experiences for your audience.
FAQs
Q:Whatare the differencesbetweenuseCallbackanduseEffecthooksinReact?
A: is used to optimize the performance of functional components by memoizing
functions, while is used to handle side effects like fetching data or updating the DOM.
Q:WhenshouldIuse useCallbackvsuseEffect?
A: Use when you want to optimize the performance of your functional component by
memoizing functions. Use when you want to handle side effects like fetching data or
updating the DOM.
Q:Whatare some commonpitfallstoavoidwhenusinguseCallbackanduseEffect?
A: Overusing or misusing these hooks, not properly defining the dependency array in , and
not being aware of closures and stale data can all lead to issues. It’s important to understand how these
hooks work and use them appropriately.
Q:HowcanItestcomponentsthatuse useCallbackanduseEffect?
A: You can use testing libraries like Jest and React Testing Library to test your components. You can also
use tools like React Developer Tools to inspect the behavior of your components and hooks.
Q:Are there any performance implicationsofusinguseCallbackvsuseEffect?
A: can improve performance by preventing unnecessary re-renders of components, but
it’s important to use it appropriately. can have performance implications if not used
properly, but it’s necessary for handling side effects in your components.
useCallback
useEffect
useCallback useEffect
useCallback useEffect
useCallback useEffect
useCallback
useEffect
useCallback
useEffect
useEffect
useCallback
useEffect
PREVIOUS ARTICLE
14 Best Books To Learn Javascript (ES6+) In 2023
From Beginner To Advanced