10

What's the different between useEffect when you pass it dependencies as the second parameter and useCallback?

Don't both essentially run the function/code passed as the first parameter whenever the dependencies passed as the second parameter change?

From what I've read the two hooks are intended to serve different purposes, but my question is whether they in actuality could be used interchangeably because they functionally do the same thing

0

5 Answers 5

22

No, They are not same.

useEffect - is used to run side effects in the component when something changes. useEffect does not return you anything. It just runs a piece of code in the component.

useCallback - Whereas useCallback returns a function, it does not execute the code actually. It is important to understand that functions are objects in Javascript. If you don't use useCallback, the function you define inside the component is re-created whenever the component rebuilds.

Example

Consider this example, this component will go in a infinite loop. Think Why?

const TestComponent = props => {
  const testFunction = () => {
    // does something.
  };

  useEffect(() => {
    testFunction();
    // The effect calls testFunction, hence it should declare it as a dependency
    // Otherwise, if something about testFunction changes (e.g. the data it uses), the effect would run the outdated version of testFunction
  }, [testFunction]);
};

Because on each render the testFunction would be re-created and we already know that useEffect will run the code when ever the testFunction changes. And since testFunction changes on each render, the useEffect will keep on running, and hence an infinite loop.

To fix this, we have to tell react, hey please don't re-create the testFunction on each render, create it only on first render (or when something changes on which it depends).

const TestComponent = props => {
  const testFunction = useCallback(() => {
    // does something.
  }, []);

  useEffect(() => {
    testFunction();
    // The effect calls testFunction, hence it should declare it as a dependency
    // Otherwise, if something about testFunction changes (e.g. the data it uses), the effect would run the outdated version of testFunction
  }, [testFunction]);
};

This won't be a infinite loop, since instance of testFunction will change only on first render and hence useEffect will run only once.

Sign up to request clarification or add additional context in comments.

1 Comment

That's not an infinite loop, unless the testFunction does something to make the component re-render. The useEffect gets called once on every render; and it stops until the next render.
13

They're too different.

useEffect will run the function inside when the dependency array changes.

useCallback will create a new function when the dependency array changes.

You can't switch useEffect with useCallback alone because you also need the logic to run the newly created function. (I suppose you could implement this if you used a ref as well, but that'd be quite strange.)

You can't switch useCallback with useEffect because you very often don't want to run the newly created function immediately - rather, you usually want to pass it as a prop to some other component.

useCallback primarily exists for optimization purposes, to reduce re-renders of a child component.

Comments

1

useEffect will run the function inside when the dependency array changes.

useCallback will create a new function when the dependency array changes.

Let's take an example, If I run the below code and click the first button it'll always rerender MemoComponent as well. Why because every time we are passing new onClick function to this. To avoid re-rendering of MemoComponent what we can do is wrap onClick to useCallback. Whenever you want to create a new function pass state to the dependence array.

If you want to perform some action on state change you can write inside useEffect.

const Button = ({ onClick }) => {
  console.log("Render");
  return <button onClick={onClick}>Click</button>;
};


const MemoComponent = React.memo(Button);
export default function Home() {
    const [state, setState] = useState(1);

    useEffect(() => {
        console.log(state); // this will execute when state changes
    }, [state]);

    const onClick = () => {};

    // const onClick = useCallback(() => {},[])
    return (
        <main>
        <button onClick={() => setState(1 + state)}>{state}</button>
        <MemoComponent onClick={onClick} />
        </main>
    );
}

Comments

0

useEffect

It's the alternative for the class component lifecycle methods componentDidMount, componentWillUnmount, componentDidUpdate, etc. You can also use it to create a side effect when dependencies change, i.e. "If some variable changes, do this".

Whenever you have some logic that is executed as reaction to a state change or before a change is about to happen.

useEffect(() => {
  // execute when state changed
  () => {
    // execute before state is changed
  }
}, [state]);

OR

useEffect(() => {
  // execute when state changed
  () => {
    // execute before state is changed
  }
}, []);

useCallback

On every render, everything that's inside a functional component will run again. If a child component has a dependency on a function from the parent component, the child will re-render every time the parent re-renders even if that function "doesn't change" (the reference changes, but what the function does won't). It's used for optimization by avoiding unnecessary renders from the child, making the function change the reference only when dependencies change. You should use it when a function is a dependency of a side effect e.g. useEffect.

Whenever you have a function that is depending on certain states. This hook is for performance optimization and prevents a function inside your component to be reassigned unless the depending state is changed.

const myFunction = useCallback(() => {
  // execute your logic for myFunction
}, [state]);

Without useCallback, myFunction will be reassigned on every render. Therefore it uses more compute time as it would with useCallback.

Comments

0

useCallback(): This React hook is used to cache (memoize) a function. It remembers the function, so the reference doesn't change unless the dependencies do. This does not run the function; it only remembers it.

example: Lets take this password generator code.

const passwordGenerator = useCallback(() => {
    let pass = "";
    let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    if (numberAllowed) str += "0123456789";
    if (charAllowed) str += "!@#$%^&*(){}[]~`-";
    for (let i = 0; i < length; i++) {
      let char = Math.floor(Math.random() * str.length);
      pass += str.charAt(char);
    }
    setPassword(pass);
  }, [length, numberAllowed, charAllowed]);
 

Whenever any dependencies from

[length, numberAllowed, charAllowed]

This dependency array changes, Only values of these dependencies within the function changes Note: The function is memoized (not recreated) unless dependencies change. But it still runs if you call it explicitly, like we did inside useEffect

So, we can say that useCallback is used for performance optimization. It memoizes the function to avoid unnecessary re-creations, and it will only be re-created when the dependencies change—not just on every render.

useEffect(): This React hook is used to run functions or side effects after the render when dependencies change. It can be understood as something changing when the count changes.

in this example side Effect passwordGenerator() whenever a dependency changes from dependency array.

 useEffect(()=>{
    passwordGenerator();

  },[length,passwordGenerator,numberAllowed,charAllowed,]);

In this case:

  • useEffect runs after render.

  • It calls the memoized passwordGenerator() function.

  • The effect re-runs whenever any dependency changes: length, numberAllowed, charAllowed, or the function itself (though it's memoized, React still tracks it for safety

useEffect() is a React Hook used to run side effects in a component, such as:

  • Fetching data

  • Updating the DOM

  • Running logic after a render

It runs the callback after the component renders and whenever the dependencies in its array change.

🔁 Summary

Hooks Purpose Runs when
useCallback Memoizes a function Dependencies change
useEffect Runs a side-effect after render Dependencies change (or on mount if empty

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.