This code calls `computeExpensiveValue(a, b)`. But if the inputs `[a, b]` haven't changed since the last value, `useMemo` skips calling it a second time and simply reuses the last value it returned.
Conveniently, this also lets you skip an expensive re-render of a child:
`useMemo` is treated as a hint rather than guarantee. React may still choose to "forget" some previously memoized values to free memory, and recalculate them on next render.
Conveniently, `useMemo` also lets you skip an expensive re-render of a child:
```js
function Parent({ a, b }) {
@ -361,6 +364,67 @@ function Parent({ a, b }) {
Note that this approach won't work in a loop because Hook calls [can't](/docs/hooks-rules.html) be placed inside loops. But you can extract a separate component for the list item, and call `useMemo` there.
### How to create expensive objects lazily?
`useMemo` lets you [memoize an expensive calculation](#how-to-memoize-calculations) if the inputs are the same. However, it only serves as a hint, and doesn't *guarantee* the computation won't re-run. But sometimes need to be sure an object is only created once.
**The first common use case is when creating the initial state is expensive:**
React will only call this function during the first render. See the [`useState` API reference](/docs/hooks-reference.html#usestate).
**You might also occasionally want to avoid re-creating the `useRef()` initial value.** For example, maybe you want to ensure some imperative class instance only gets created once:
```js
function Image(props) {
// ⚠️ IntersectionObserver is created on every render
`useRef`**does not** accept a special function overload like `useState`. Instead, you can write your own function that creates and sets it lazily:
```js
function Image(props) {
const ref = useRef(null);
// ✅ IntersectionObserver is created lazily once
function getObserver() {
let observer = ref.current;
if (observer !== null) {
return observer;
}
let newObserver = new IntersectionObserver(onIntersect);
ref.current = newObserver;
return newObserver;
}
// When you need it, call getObserver()
// ...
}
```
This avoids creating an expensive object until it's truly needed for the first time. If you use Flow or TypeScript, you can also give `getObserver()` a non-nullable type for convenience.
### Are Hooks slow because of creating functions in render?
No. In modern browsers, the raw performance of closures compared to classes doesn't differ significantly except in extreme scenarios.
@ -497,6 +561,7 @@ function useEventCallback(fn, dependencies) {
In either case, we **don't recommend this pattern** and only show it here for completeness. Instead, it is preferable to [avoid passing callbacks deep down](#how-to-avoid-passing-callbacks-down).
## Under the Hood
### How does React associate Hook calls with components?
@ -290,6 +290,8 @@ Pass a "create" function and an array of inputs. `useMemo` will only recompute t
If no array is provided, a new value will be computed whenever a new function instance is passed as the first argument. (With an inline function, on every render.)
**Don't rely on `useMemo` for correctness.** React treats it as an optimization hint and does not *guarantee* to retain the memoized value. For example, React may choose to "forget" some previously memoized values to free memory, and recalculate them on next render.
> Note
>
> The array of inputs is not passed as arguments to the function. Conceptually, though, that's what they represent: every value referenced inside the function should also appear in the inputs array. In the future, a sufficiently advanced compiler could create this array automatically.