You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
344
345
345
-
Conveniently, this also lets you skip an expensive re-render of a child:
346
+
`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.
347
+
348
+
Conveniently, `useMemo` also lets you skip an expensive re-render of a child:
346
349
347
350
```js
348
351
functionParent({ a, b }) {
@@ -361,6 +364,67 @@ function Parent({ a, b }) {
361
364
362
365
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.
363
366
367
+
### How to create expensive objects lazily?
368
+
369
+
`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.
370
+
371
+
**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).
392
+
393
+
**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:
394
+
395
+
```js
396
+
functionImage(props) {
397
+
// ⚠️ 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:
404
+
405
+
```js
406
+
functionImage(props) {
407
+
constref=useRef(null);
408
+
409
+
// ✅ IntersectionObserver is created lazily once
410
+
functiongetObserver() {
411
+
let observer =ref.current;
412
+
if (observer !==null) {
413
+
return observer;
414
+
}
415
+
let newObserver =newIntersectionObserver(onIntersect);
416
+
ref.current= newObserver;
417
+
return newObserver;
418
+
}
419
+
420
+
// When you need it, call getObserver()
421
+
// ...
422
+
}
423
+
```
424
+
425
+
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.
426
+
427
+
364
428
### Are Hooks slow because of creating functions in render?
365
429
366
430
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) {
497
561
498
562
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).
499
563
564
+
500
565
## Under the Hood
501
566
502
567
### How does React associate Hook calls with components?
Copy file name to clipboardExpand all lines: content/docs/hooks-reference.md
+2Lines changed: 2 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -290,6 +290,8 @@ Pass a "create" function and an array of inputs. `useMemo` will only recompute t
290
290
291
291
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.)
292
292
293
+
**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.
294
+
293
295
> Note
294
296
>
295
297
> 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.
0 commit comments