ReactJavaScriptBest PracticesPerformance

Why You Shouldn't Define Functions Inside useEffect in React

Nkandu Akim Lukeshi

Nkandu Akim Lukeshi

Full Stack Developer
2024-06-282 min read
Why You Shouldn't Define Functions Inside useEffect in React

Introduction

React's useEffect hook is super useful for handling side effects like fetching data, subscribing to services, or changing the DOM after a component renders. However, there's a common mistake developers make: defining functions directly inside useEffect. While it might seem convenient, it can lead to problems.

The Problem

When you define a function inside useEffect, a new version of that function is created every time the component renders. This can cause useEffect to run more often than needed if the function is in the dependency array.

useEffect(() => {
  const fetchData = async () => {
    // Fetch data
  };
  
  fetchData();
}, []); // This creates fetchData on every render

1. Avoid Unnecessary Re-Runs

The function gets recreated every render, which can cause performance issues. Instead, define the function outside:

const fetchData = async () => {
  // Fetch data
};

useEffect(() => {
  fetchData();
}, []); // fetchData doesn't change between renders

2. Cleaner and Easier to Read

When you write functions outside useEffect, your code looks cleaner and is easier to understand. The useEffect block clearly shows when the effect runs, and the function definition shows what it does.

const fetchData = async () => {
  // Clear what this function does
};

useEffect(() => {
  fetchData(); // Clear when it runs
}, []);

3. Easier to Test

If you define functions outside useEffect, you can test them separately. This makes it easier to write unit tests for your functions without worrying about the React environment.

Pro Tip: Extracting functions outside useEffect makes them reusable across multiple effects or components.

4. Better Control Over Dependencies

Handling the dependency array in useEffect can be tricky. Defining functions inside can cause unnecessary re-runs. By keeping functions outside, you can manage dependencies better.

const fetchData = async () => {
  // Fetch data
};

useEffect(() => {
  fetchData();
}, [/* only necessary dependencies */]);

When You Must Define Functions Inside

Sometimes you need to define functions inside useEffect when they depend on props or state. In these cases, use useCallback to optimize:

const fetchData = useCallback(async (id) => {
  // Fetch data using id
}, [id]);

useEffect(() => {
  fetchData(userId);
}, [fetchData, userId]);

Conclusion

Defining functions inside useEffect might seem easier, but it can cause bugs, performance issues, and messy code. By writing functions outside and calling them inside useEffect, you make your code cleaner, more efficient, and easier to maintain. This small change can greatly improve your React applications.

Nkandu Akim Lukeshi

Nkandu Akim Lukeshi

Full Stack Developer

Passionate about building scalable web applications and sharing knowledge with the developer community. Experienced in React, Next.js, and modern web technologies.

© 2025 Nkandu Lukeshi Akim. All rights reserved.