Avoiding Memory Leaks
Learn how to mitigating memory leaks in React by using refs to handle asynchronous operations and prevent unwanted updates after component unmount.
We'll cover the following...
Addressing memory leaks in async operations
Historically speaking, a ref was created to hold a DOM element, but people later found it very effective in addressing tricky problems. One problem is memory leaks, which happen when performing an async action. The thing about an async operation is that the callback function gets invoked later. By the time the callback is handled, there's a chance the component (or any variable associated with the component) is not valid anymore.
Let's say we fetch an API and display the result as text:
const Title = () => {// State variable 'text' to store the fetched textconst [text, setText] = useState("");// useEffect to fetch data from "https://google.com" on component mountuseEffect(() => {// Fetch data from the specified URLfetch("https://google.com").then(res => {// Extract the title from the response and set it in the statereturn res.text();}).then(title => {setText(title);}).catch(error => {// Handle errors, such as network issues or CORS restrictionsconsole.error("Error fetching data:", error);});}, []); // Empty dependency array ensures the effect runs only once during component mount// Render an h1 element displaying the fetched textreturn <h1>{text}</h1>;}
The preceding code is a common fetch process, but there's a memory leak lurking out there. When it happens, the browser outputs the following message:
Although React is efficient enough to display it as a warning message under development build, it's actually an error, as it indicates a memory leak in the message. The strange thing about this leak is that most of the time, the UI continues to function even after the message. So, should we ignore this message? Absolutely not.
Let's build the crime scene and try to understand what exactly happens under this message:
const App = ({ flag }) => {// If 'flag' is true, render the Title component; otherwise, render nothingif (flag) return <Title />;// If 'flag' is false, return null to render nothingreturn null;}
Say we have an ...