Learn React Hooks by looking under the hood of a video chat app 
Tags: react, webdev, javascript
Published: 2021-04-01 05:48:22

Like most developers I know, I learn a lot every day at work. That's part of why I wanted to make programming part of my job! 

I really like getting to immediately *apply* new things, and that helps me learn better, too. Despite reading lots of explainers and a few tutorials, I didn't really start to grok React Hooks until I needed to dig into the [Daily React video chat demo](https://github.com/daily-demos/call-object-react?utm_source=dev&utm_campaign=learn-react-hooks). 

When I think about the roles `useEffect`, `useMemo`, and `useCallback` play in a video chat app, something a lot of us use every day, I better remember how each hook works and recognize other opportunities to use them. 

![Dustin Hoffman smiles as Captain Hook](https://media.giphy.com/media/B4ZgcoPTHYXL2/giphy.gif) 

In case reading about that practical application could help you too, I decided to write about it! After a quick Hooks refresher, we'll look at an example of each these Hooks in the Daily [demo app](https://call-object-react.netlify.app/?utm_source=dev&utm_campaign=learn-react-hooks), and why we decided to use each. 

> _I mentioned in my last post about [avoiding global variables](https://dev.to/kimberleejohnson/how-i-learned-to-avoid-implied-globals-and-why-16ad) that I'm trying to get better about sharing what my colleagues teach me. This round is brought to us by the inimitable [Jess Mitchell](https://twitter.com/gemontracks), who I am so grateful to work with and learn from!_


## Before we get hook'd


I really liked [Ali Spittel's]([https://dev.to/aspittel](https://dev.to/aspittel)) definition of Hooks on the [latest Ladybug podcast]([https://www.ladybug.dev/episodes/getting-hooked-on-react-part-2](https://www.ladybug.dev/episodes/getting-hooked-on-react-part-2)): 

> _"Hooks are a special type of function that allow you to hook into the component lifecycle of react components. So they allow you to do special things that a normal function wouldn't be able to do."_

This means we can do unique things when components mount, update, and unmount. Like the [docs say](https://reactjs.org/docs/hooks-overview.html), we can take advantage of state and other features without having to write class components. 

With that overview in mind, let's look at three Hooks in our video chat app: `useEffect`, `useMemo,` and `useCallback`. 

<br>
<br>
## `useEffect` to manage participant updates in state


With [`useEffect`](https://reactjs.org/docs/hooks-effect.html), we can, well, perform side effects in function components, based on state or prop changes. 

In a video chat app, lots of things happen! Participants join and leave calls, start and stop their audio and video tracks, and then some. Our UI needs to update along with these changes. For example, it needs to add and remove video tracks as participants come and go. 

The [Daily API](https://docs.daily.co/docs?utm_source=dev&utm_campaign=learn-react-hooks) fires corresponding [events](https://docs.daily.co/reference#events?utm_source=dev&utm_campaign=learn-react-hooks) as these things happen, e.g. `'participant-joined'`, `'track-stopped'`, etc. In our video chat app, we listen for these events and their handlers set our `particpantUpdated` state in response. 

Here's where `useEffect` comes in! We only need to update the UI when a change has happened, when `participantUpdated` is set. We pass `participantUpdated` as a dependency (along with the call object that contains the updated participant data) to a `useEffect` hook, so we only update our participant list when something has changed. 

```jsx
useEffect(() => {
    if (participantUpdated) {
      const list = Object.values(callObject?.participants());
      setParticipants(list);
    }
  }, [participantUpdated, callObject]);
```

That covers storing the participant list, but what about displaying participants, rendering their video and audio tracks? That's where our next hook comes in. 

<br>
<br>
## `useMemo` to re-render videos only when we have to


[`useMemo`](https://reactjs.org/docs/hooks-reference.html#usememo) returns a memoized value. [Memoized](https://en.wikipedia.org/wiki/Memoization) means a value that's the result of an expensive function call. 

There are lots of expensive calculations in a video chat app. Each participant's audio and video track alone contains loads of data, and computing that on every render would be a lot. 

Instead, we pass our `participants` state value as a dependency to the `useMemo` hook that displays our tiles. 

```jsx
const displayLargeTiles = useMemo(() => {
    const isLarge = true;
    const tiles = participants?.filter((p) => !p.local);
     return (
        <div className="large-tiles">
          {tiles?.map((t, i) => (
            <Tile
              key={`large-${i}`}
              videoTrackState={t?.tracks?.video}
              audioTrackState={t?.tracks?.audio}
              isLarge={isLarge}
              disableCornerMessage={isScreenShare}
              onClick={
                t.local
                  ? null
                  : () => {
                      sendHello(t.id);
                    }
              }
            />
          ))}
        </div>
      );
    }
  }, [participants]);
```

The `useMemo` hook lets us only change the videos displayed when the `participants` have changed, instead of recalculating on every render. 

> _Note: Because we built a video chat app with participant changes that happen often, the performance benefits from`useMemo` are significant; it saves us many recalculations. In a lot of cases, though, this hook might be more than your application needs. `useMemo` has a reputation of [being overused](https://dev.to/bnevilleoneill/you-re-overusing-usememo-rethinking-hooks-memoization-19g8), so tread with caution._

<br>
<br>
## `useCallback` to re-render `startLeavingCall()` function only when we have to


Just like `useMemo` prevents us from re-calculating values that haven't changed, [`useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback) lets us stop specific functions from re-rendering. 

In our [App.js component](https://github.com/daily-demos/call-object-react/blob/02e54fef364040175b0ec6222ba28552b69aa948/src/components/App/App.js?utm_source=dev&utm_campaign=learn-react-hooks), lots of things can trigger a re-render. But our `startLeavingCall` function, for example, only needs to re-render if the `callObject`, which stores data about our call, or our `appState` changes. This is because the function does different things depending on those values. 

We pass `callObject` and `appState` as our dependencies. 

```jsx
/**
   * Starts leaving the current call.
   */
  const startLeavingCall = useCallback(() => {
    if (!callObject) return;
    // If we're in the error state, we've already "left", so just clean up
    if (appState === STATE_ERROR) {
      callObject.destroy().then(() => {
        setRoomUrl(null);
        setCallObject(null);
        setAppState(STATE_IDLE);
      });
    } else {
      setAppState(STATE_LEAVING);
      callObject.leave();
    }
  }, [callObject, appState]);
```

<br>
<br>
## Hook'd and wanting more?


![Rufio from the movie Hook](https://media.giphy.com/media/oiYnN3ba0YPkY/giphy.gif)

I hope this helped make Hooks feel a little more applicable! Can you think of any new ways to apply `useEffect` or `useMemo`, or `useCallback` in apps that you're building? Tell me in the comments!  Especially tell me if you'll be building any video (or [audio!](https://www.daily.co/blog/how-to-build-a-billion-dollar-audio-app-in-a-weekend/)) apps. You can give me a shout over on [Twitter too](https://twitter.com/kimeejohnson)!