loading...
Cover image for How to write more performant functional React Components

How to write more performant functional React Components

bwighthunter profile image Blake Wight ・2 min read

What are you on about?

When writing React with hooks, I've seen a lot of properties of functional components go un-memoized. In my opinion, this is almost always a no-no.

This is generally not a good practice because of how React works. Anything that is not memoized is redefined on every re-render. So in general, my rule is to memoize everything defined in the functional component and move everything else out of the component into the global scope.

Not only does this speed up the performance of the thing that you defined, but not doing this has a compounding effect. If the thing you forgot to memoize is depended on (meaning in the dependency array of useMemo or useCallback) by another property, that property will be redefined on every render as well.

Variables that are defined globally do not get redefined when re-renders happen so they can be used without worrying about causing redefinitions.

Say what?

Here is a nice before example from a personal project (ignore what is/isn't defined as far as imports):

const { Title } = Typography;

const UserScreen = () => {
  const db = firebaseApp.firestore();
  const { user, logout } = useContext(AuthContext);

  const onSubmit =
    async (newUserProperties) => {
      return await db
        .collection(DB.COLLECTIONS.USERS)
        .doc(user.uid)
        .update(newUserProperties);
    }

  return (...);
};

In this case, the firebaseApp.firestore() operation would be called on every render. Not fun. And then even if we threw the onSubmit function in a useCallback with db in the dependency array, that would be redefined on every render as well. So you don't even get credit for almost doing it right!

Prove it

Here is a codesandbox that illustrates my point: https://codesandbox.io/s/relaxed-pasteur-7spqq?file=/src/App.js

Photo by Max Frajer on Unsplash

Posted on by:

bwighthunter profile

Blake Wight

@bwighthunter

Front-end developer mostly working with React. Experience in python and ci/cd.

Discussion

markdown guide
 

I'm gonna have to disagree. That's premature optimization, and potentially a cure worse than the disease in terms of memory overhead. Reach for useMemo and/or useCallback when rerenders are causing perf issues, and look to things like more localized context (if you're using it), offloading expensive computations to web workers, etc. first.

 

The Kent C. Dodds article @exclipy shared is an excellent resource, BTW.

 

On your codesandbox: you should remove the useCallback. It's not doing anything but overhead.

 

i would think not using useCallback creates overhead, without it every render the function is recreated

 

Also with it, the function is created on every render. See kentcdodds.com/blog/usememo-and-us...