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
*[Can I skip an effect on updates?](#can-i-skip-an-effect-on-updates)
@@ -451,6 +452,60 @@ Try to avoid this pattern if possible.
451
452
452
453
While you shouldn't need this often, you may expose some imperative methods to a parent component with the [`useImperativeHandle`](/docs/hooks-reference.html#useimperativehandle) Hook.
453
454
455
+
### How can I measure a DOM node? {#how-can-i-measure-a-dom-node}
456
+
457
+
In order to measure the position or size of a DOM node, you can use a [callback ref](/docs/refs-and-the-dom.html#callback-refs). React will call that callback whenever the ref gets attached to a different node. Here is a [small demo](https://codesandbox.io/s/l7m0v5x4v9):
458
+
459
+
```js{4-8,12}
460
+
function MeasureExample() {
461
+
const [height, setHeight] = useState(0);
462
+
463
+
const measuredRef = useCallback(node => {
464
+
if (node !== null) {
465
+
setHeight(node.getBoundingClientRect().height);
466
+
}
467
+
}, []);
468
+
469
+
return (
470
+
<>
471
+
<h1 ref={measuredRef}>Hello, world</h1>
472
+
<h2>The above header is {Math.round(height)}px tall</h2>
473
+
</>
474
+
);
475
+
}
476
+
```
477
+
478
+
We didn't choose `useRef` in this example because an object ref doesn't notify us about *changes* to the current ref value. Using a callback ref ensures that [even if a child component displays the measured node later](https://codesandbox.io/s/818zzk8m78) (e.g. in response to a click), we still get notified about it in the parent component and can update the measurements.
479
+
480
+
Note that we pass `[]` as a dependency array to `useCallback`. This ensures that our ref callback doesn't change between the re-renders, and so React won't call it unnecessarily.
481
+
482
+
If you want, you can [extract this logic](https://codesandbox.io/s/m5o42082xy) into a reusable Hook:
483
+
484
+
```js{2}
485
+
function MeasureExample() {
486
+
const [rect, ref] = useClientRect();
487
+
return (
488
+
<>
489
+
<h1 ref={ref}>Hello, world</h1>
490
+
{rect !== null &&
491
+
<h2>The above header is {Math.round(rect.height)}px tall</h2>
492
+
}
493
+
</>
494
+
);
495
+
}
496
+
497
+
function useClientRect() {
498
+
const [rect, setRect] = useState(null);
499
+
const ref = useCallback(node => {
500
+
if (node !== null) {
501
+
setRect(node.getBoundingClientRect());
502
+
}
503
+
}, []);
504
+
return [rect, ref];
505
+
}
506
+
```
507
+
508
+
454
509
### What does `const [thing, setThing] = useState()` mean? {#what-does-const-thing-setthing--usestate-mean}
455
510
456
511
If you're not familiar with this syntax, check out the [explanation](/docs/hooks-state.html#tip-what-do-square-brackets-mean) in the State Hook documentation.
@@ -853,7 +908,7 @@ function Form() {
853
908
const [text, updateText] = useState('');
854
909
const textRef = useRef();
855
910
856
-
useLayoutEffect(() => {
911
+
useEffect(() => {
857
912
textRef.current = text; // Write it to the ref
858
913
});
859
914
@@ -894,7 +949,7 @@ function useEventCallback(fn, dependencies) {
894
949
throw new Error('Cannot call an event handler while rendering.');
If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the [`Object.is` comparison algorithm](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).)
99
99
100
+
Note that React may still need to render that specific component again before bailing out. That shouldn't be a concern because React won't unnecessarily go "deeper" into the tree. If you're doing expensive calculations while rendering, you can optimize them with `useMemo`.
101
+
100
102
### `useEffect` {#useeffect}
101
103
102
104
```js
@@ -173,12 +175,26 @@ The array of dependencies is not passed as arguments to the effect function. Con
173
175
### `useContext` {#usecontext}
174
176
175
177
```js
176
-
constcontext=useContext(Context);
178
+
constvalue=useContext(MyContext);
177
179
```
178
180
179
-
Accepts a context object (the value returned from `React.createContext`) and returns the current context value, as given by the nearest context provider for the given context.
181
+
Accepts a context object (the value returned from `React.createContext`) and returns the current context value for that context. The current context value is determined by the `value` prop of the nearest `<MyContext.Provider>` above the calling component in the tree.
182
+
183
+
When the nearest `<MyContext.Provider>` above the component updates, this Hook will trigger a rerender with the latest context `value` passed to that `MyContext` provider.
184
+
185
+
Don't forget that the argument to `useContext` must be the *context object itself*:
186
+
187
+
***Correct:**`useContext(MyContext)`
188
+
***Incorrect:**`useContext(MyContext.Consumer)`
189
+
***Incorrect:**`useContext(MyContext.Provider)`
180
190
181
-
When the provider updates, this Hook will trigger a rerender with the latest context value.
191
+
A component calling `useContext` will always re-render when the context value changes. If re-rendering the component is expensive, you can [optimize it by using memoization](https://github.com/facebook/react/issues/15156#issuecomment-474590693).
192
+
193
+
>Tip
194
+
>
195
+
>If you're familiar with the context API before Hooks, `useContext(MyContext)` is equivalent to `static contextType = MyContext` in a class, or to `<MyContext.Consumer>`.
196
+
>
197
+
>`useContext(MyContext)` only lets you *read* the context and subscribe to its changes. You still need a `<MyContext.Provider>` above in the tree to *provide* the value for this context.
182
198
183
199
## Additional Hooks {#additional-hooks}
184
200
@@ -285,6 +301,8 @@ function Counter({initialCount}) {
285
301
286
302
If you return the same value from a Reducer Hook as the current state, React will bail out without rendering the children or firing effects. (React uses the [`Object.is` comparison algorithm](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).)
287
303
304
+
Note that React may still need to render that specific component again before bailing out. That shouldn't be a concern because React won't unnecessarily go "deeper" into the tree. If you're doing expensive calculations while rendering, you can optimize them with `useMemo`.
305
+
288
306
### `useCallback` {#usecallback}
289
307
290
308
```js
@@ -356,7 +374,16 @@ function TextInputWithFocusButton() {
356
374
}
357
375
```
358
376
359
-
Note that `useRef()` is useful for more than the `ref` attribute. It's [handy for keeping any mutable value around](/docs/hooks-faq.html#is-there-something-like-instance-variables) similar to how you'd use instance fields in classes.
377
+
Essentially, `useRef` is like a "box" that can hold a mutable value in its `.current` property.
378
+
379
+
You might be familiar with refs primarily as a way to [access the DOM](/docs/refs-and-the-dom.html). If you pass a ref object to React with `<div ref={myRef} />`, React will set its `.current` property to the corresponding DOM node whenever that node changes.
380
+
381
+
However, `useRef()` is useful for more than the `ref` attribute. It's [handy for keeping any mutable value around](/docs/hooks-faq.html#is-there-something-like-instance-variables) similar to how you'd use instance fields in classes.
382
+
383
+
This works because `useRef()` creates a plain JavaScript object. The only difference between `useRef()` and creating a `{current: ...}` object yourself is that `useRef` will give you the same ref object on every render.
384
+
385
+
Keep in mind that `useRef`*doesn't* notify you when its content changes. Mutating the `.current` property doesn't cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a [callback ref](/docs/hooks-faq.html#how-can-i-measure-a-dom-node) instead.
386
+
360
387
361
388
### `useImperativeHandle` {#useimperativehandle}
362
389
@@ -389,7 +416,11 @@ Prefer the standard `useEffect` when possible to avoid blocking visual updates.
389
416
390
417
> Tip
391
418
>
392
-
> If you're migrating code from a class component, `useLayoutEffect` fires in the same phase as `componentDidMount` and `componentDidUpdate`, so if you're unsure of which effect Hook to use, it's probably the least risky.
419
+
> If you're migrating code from a class component, note `useLayoutEffect` fires in the same phase as `componentDidMount` and `componentDidUpdate`. However, **we recommend starting with `useEffect` first** and only trying `useLayoutEffect` if that causes a problem.
420
+
>
421
+
>If you use server rendering, keep in mind that *neither*`useLayoutEffect` nor `useEffect` can run until the JavaScript is downloaded. This is why React warns when a server-rendered component contains `useLayoutEffect`. To fix this, either move that logic to `useEffect` (if it isn't necessary for the first render), or delay showing that component until after the client renders (if the HTML looks broken until `useLayoutEffect` runs).
422
+
>
423
+
>To exclude a component that needs layout effects from the server-rendered HTML, render it conditionally with `showChild && <Child />` and defer showing it with `useEffect(() => { setShowChild(true); }, [])`. This way, the UI doesn't appear broken before hydration.
0 commit comments