useEffect, useMemo & useCallback
These next three hooks are relatively similar, and fairly simple, so this lesson should go quick.
useEffect
Lets take a look at the type definition for **useEffect**
.
This type definition tells us three things:
**useEffect**
takes a function, called EffectCallback, as it's first parameter.
- EffectCallback has to return either
**void**
, or a cleanup function. That cleanup function has to return**void**
.
**useEffect**
can optionally take a list of dependencies, which is just an array of**any**
.
The only thing to keep in mind when using **useEffect**
in TypeScript is that the EffectCallback has to return **void**
, which means it returns nothing, or a cleanup function. If we do return a cleanup function, it can't return anything either.
This only really becomes a problem if we are using an implicit return with an arrow function, like this:
Usually it's best to use the non-implicitly returning form of arrow functions with **useEffect**
.
It's also worth noting that the seldom-used **useLayoutEffect**
hook has exactly the same type definition as **useEffect**
.
useMemo
Since it's short, we'll also look at the type definition for **useMemo**
:
function useMemo<T>(factory: () => T, deps: DependencyList): T;
**useMemo**
is a generic function. We pass it a function, and whatever that function returns is the return value of **useMemo**
. I've never had a situation where TypeScript didn't properly infer the value of **T**
based on what I passed in, so you'll likely never have to assign a type to **T**
The only thing to note here is that the dependency list for **useMemo**
is not optional - you are required to provide one. Otherwise, what's the point of using **useMemo**
? Without a dependency list, the value returned from **useMemo**
will be referentially different between renders.
useCallback
**useCallback**
is just like **useMemo**
, except it only memoizes functions for us. Here's the type definition for **useCallback**
:
This is mostly the same as **useMemo**
except the generic type that represents the return value is constrained to be a function. That's because **useCallback**
is specifically used for memoizing functions, so naturally we have to pass a function in.
Like **useMemo**
, we also must provide a dependency list. Otherwise, we'll get a warning. It's just TypeScripts way of trying to help you out.