You probably don't need that useCallback call

ยท

0 min read

useCallback for those of you who may not know is a hook that let's us cache our functions. Now what that means if we can "save" the function. Let me break that down: When our components re-render React creates new functions, nothing in the function actually changes but since everything is an object in JavaScript a new object is created so useCallback basically just saves the old object. It is common practice to wrap your functions in useCallback, heck some wrap every function in their component in it citing performance gains etc. Thing is, that's not really true, you aren't really benefiting from doing that. In my opinion, you should only wrap a function in useCallback if you might enter an infinite loop otherwise, if it's performance you're after React.memo or the useMemo hook are better alternatives. You might be wondering "how will I know i'll enter an infinite loop?". In some cases you don't, you hit the loop, React stops it and you fix it but there is a definitive case where you could hit an infinite loop and it's also the most common:

  • useEffect Having a dependency on a function that sets states Let me break it down as simply as possible then show a code example: Say you have a function that sets some state and you need to call it in useEffect and as such list it as a dependency (i.e useEffect runs whenever the function changes). The chain would go:
  • The function gets called
  • Sets state
  • Setting state causes the component to re-render
  • A new function is created
  • useEffect gets called because the function has changed
  • The function gets called again and so on... The way out of it would be to wrap the function in useCallback so whenever we set state and the component re-renders we don't create a new function and as such useEffect never gets called. Now let's do that in code.
    // without useCallback
    import React, {useState, useEffect} from "react";
    import axios from "axios";
    function App(){
    const [data, setData] = useState(null);
    useEffect(()=> {
    getData();
    }, [getData]);
    const getData = ()=> {
    axios.get("https://dummydata.com").then(resp=> setData(resp.data)).catch(err=> console.log(err));
    }
    export default App;
    
    In the above, without useCallback we enter an infinite loop. Let's fix that.
    // with useCallback
    import React, {useState, useEffect, useCallback} from "react";
    import axios from "axios";
    function App(){
    const [data, setData] = useState(null);
    useEffect(()=> {
    getData();
    }, [getData]);
    const useCallback(getData = ()=> {
    axios.get("https://dummydata.com").then(resp=> setData(resp.data)).catch(err=> console.log(err));
    },[])
    export default App;
    
    In conclusion, useCallback is a really powerful hook that takes care of an age old problem but it's important to remember as with all Hooks - only use it if you need it.