From 905a1134c07ea24aa4e4e4351371cf77b027280a Mon Sep 17 00:00:00 2001 From: Brian Mitchell Date: Mon, 18 Mar 2019 12:24:24 -0500 Subject: [PATCH 1/5] Add React Rally 2019 (#1840) --- content/community/conferences.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/community/conferences.md b/content/community/conferences.md index e138b119a..ea8613c78 100644 --- a/content/community/conferences.md +++ b/content/community/conferences.md @@ -57,6 +57,11 @@ July 15-21, 2019. New York City, USA [Website](https://reactweek.nyc) - [Twitter](https://twitter.com/ReactWeek) +### React Rally 2019 +August 22-23, 2019. Salt Lake City, USA. + +[Website](https://www.reactrally.com/) - [Twitter](https://twitter.com/ReactRally) - [Instagram](https://www.instagram.com/reactrally/) + ### ComponentsConf 2019 {#componentsconf-2019} September 6, 2019 in Melbourne, Australia [Website](https://www.componentsconf.com.au/) - [Twitter](https://twitter.com/componentsconf) From 806da34988106c2a92c9784edc2bc0e91333ca4a Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 19 Mar 2019 15:28:18 +0000 Subject: [PATCH 2/5] Add a DOM measurement recipe to Hooks FAQ (#1843) * Add a DOM measurement recipe to Hooks FAQ * Update content/docs/hooks-faq.md Co-Authored-By: gaearon * Update content/docs/hooks-faq.md Co-Authored-By: gaearon --- content/docs/hooks-faq.md | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/content/docs/hooks-faq.md b/content/docs/hooks-faq.md index 9016fa7f4..1e68b379c 100644 --- a/content/docs/hooks-faq.md +++ b/content/docs/hooks-faq.md @@ -41,6 +41,7 @@ This page answers some of the frequently asked questions about [Hooks](/docs/hoo * [How do I implement getDerivedStateFromProps?](#how-do-i-implement-getderivedstatefromprops) * [Is there something like forceUpdate?](#is-there-something-like-forceupdate) * [Can I make a ref to a function component?](#can-i-make-a-ref-to-a-function-component) + * [How can I measure a DOM node?](#how-can-i-measure-a-dom-node) * [What does const [thing, setThing] = useState() mean?](#what-does-const-thing-setthing--usestate-mean) * **[Performance Optimizations](#performance-optimizations)** * [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. 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. +### How can I measure a DOM node? {#how-can-i-measure-a-dom-node} + +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): + +```js{4-8,12} +function MeasureExample() { + const [height, setHeight] = useState(0); + + const measuredRef = useCallback(node => { + if (node !== null) { + setHeight(node.getBoundingClientRect().height); + } + }, []); + + return ( + <> +

Hello, world

+

The above header is {Math.round(height)}px tall

+ + ); +} +``` + +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. + +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. + +If you want, you can [extract this logic](https://codesandbox.io/s/m5o42082xy) into a reusable Hook: + +```js{2} +function MeasureExample() { + const [rect, ref] = useClientRect(); + return ( + <> +

Hello, world

+ {rect !== null && +

The above header is {Math.round(rect.height)}px tall

+ } + + ); +} + +function useClientRect() { + const [rect, setRect] = useState(null); + const ref = useCallback(node => { + if (node !== null) { + setRect(node.getBoundingClientRect()); + } + }, []); + return [rect, ref]; +} +``` + + ### What does `const [thing, setThing] = useState()` mean? {#what-does-const-thing-setthing--usestate-mean} 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. From ac4aa6546e413bc6bdc6d8191081b739fbc6fb27 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 19 Mar 2019 17:12:44 +0000 Subject: [PATCH 3/5] Add more explanations to Hooks API page (#1845) * Add more explanations to API page * static * add info about useLayoutEffect * Update content/docs/hooks-reference.md Co-Authored-By: gaearon * nits * nit --- content/docs/hooks-faq.md | 4 ++-- content/docs/hooks-reference.md | 39 ++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/content/docs/hooks-faq.md b/content/docs/hooks-faq.md index 1e68b379c..7d2953293 100644 --- a/content/docs/hooks-faq.md +++ b/content/docs/hooks-faq.md @@ -908,7 +908,7 @@ function Form() { const [text, updateText] = useState(''); const textRef = useRef(); - useLayoutEffect(() => { + useEffect(() => { textRef.current = text; // Write it to the ref }); @@ -949,7 +949,7 @@ function useEventCallback(fn, dependencies) { throw new Error('Cannot call an event handler while rendering.'); }); - useLayoutEffect(() => { + useEffect(() => { ref.current = fn; }, [fn, ...dependencies]); diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index 4daf0f191..f2cc087d4 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -97,6 +97,8 @@ const [state, setState] = useState(() => { 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).) +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`. + ### `useEffect` {#useeffect} ```js @@ -173,12 +175,24 @@ The array of dependencies is not passed as arguments to the effect function. Con ### `useContext` {#usecontext} ```js -const context = useContext(Context); +const value = useContext(MyContext); ``` -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. +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 `` above the calling component in the tree. + +When the nearest `` above the component updates, this Hook will trigger a rerender with the latest context `value` passed to that `MyContext` provider. -When the provider updates, this Hook will trigger a rerender with the latest context value. +Don't forget that the argument to `useContext` must be the *context object itself*: + + * **Correct:** `useContext(MyContext)` + * **Incorrect:** `useContext(MyContext.Consumer)` + * **Incorrect:** `useContext(MyContext.Provider)` + +>Tip +> +>If you're familiar with the context API before Hooks, `useContext(MyContext)` is equivalent to `static contextType = MyContext` in a class, or to ``. +> +>`useContext(MyContext)` only lets you *read* the context and subscribe to its changes. You still need a `` above in the tree to *provide* the value for this context. ## Additional Hooks {#additional-hooks} @@ -285,6 +299,8 @@ function Counter({initialCount}) { 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).) +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`. + ### `useCallback` {#usecallback} ```js @@ -356,7 +372,16 @@ function TextInputWithFocusButton() { } ``` -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. +Essentially, `useRef` is like a "box" that can hold a mutable value in its `.current` property. + +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 `
`, React will set its `.current` property to the corresponding DOM node whenever that node changes. + +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. + +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. + +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. + ### `useImperativeHandle` {#useimperativehandle} @@ -389,7 +414,11 @@ Prefer the standard `useEffect` when possible to avoid blocking visual updates. > Tip > -> 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. +> 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. +> +>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). +> +>To exclude a component that needs layout effects from the server-rendered HTML, render it conditionally with `showChild && ` and defer showing it with `useEffect(() => { setShowChild(true); }, [])`. This way, the UI doesn't appear broken before hydration. ### `useDebugValue` {#usedebugvalue} From b1bc193dbad464f7c659b10f3f57e37e265a063e Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 19 Mar 2019 22:09:21 +0000 Subject: [PATCH 4/5] Document useContext bailout strategy (#1848) --- content/docs/hooks-reference.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index f2cc087d4..98c2e14c0 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -188,6 +188,8 @@ Don't forget that the argument to `useContext` must be the *context object itsel * **Incorrect:** `useContext(MyContext.Consumer)` * **Incorrect:** `useContext(MyContext.Provider)` +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). + >Tip > >If you're familiar with the context API before Hooks, `useContext(MyContext)` is equivalent to `static contextType = MyContext` in a class, or to ``. From 36b96a08d20eb44d41f644a7048167ef345a752d Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 21 Mar 2019 10:58:19 +0100 Subject: [PATCH 5/5] Handle sync updates --- content/docs/hooks-reference.md | 51 ++++++++++++--------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index 0962f2cd4..70eb8444b 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -176,29 +176,23 @@ Le tableau d'entrées n'est pas fourni comme argument à la fonction d'effet. Co const value = useContext(MyContext); ``` -<<<<<<< HEAD -Accepte un objet contexte (la valeur renvoyée par `React.createContext`), et renvoie la valeur actuelle du contexte telle qu'elle est donnée par le fournisseur de contexte le plus proche pour l’objet contexte utilisé. +Accepte un objet contexte (la valeur renvoyée par `React.createContext`), et renvoie la valeur actuelle du contexte. Celle-ci est déterminée par la prop `value` du plus proche `` au-dessus du composant dans l'arbre. -Quand le fournisseur met la valeur à jour, ce Hook va déclencher un nouveau rendu avec la valeur la plus récente du contexte. -======= -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 `` above the calling component in the tree. +Quand le plus proche `` au-dessus du composant est mis à jour, ce Hook va déclencher un rafraîchissement avec la `value` la plus récente passée au fournisseur `MyContext`. -When the nearest `` above the component updates, this Hook will trigger a rerender with the latest context `value` passed to that `MyContext` provider. +N’oubliez pas que l’argument de `useContext` doit être *l’objet contexte lui-même* : -Don't forget that the argument to `useContext` must be the *context object itself*: + * **Correct :** `useContext(MyContext)` + * **Erroné :** `useContext(MyContext.Consumer)` + * **Erroné :** `useContext(MyContext.Provider)` - * **Correct:** `useContext(MyContext)` - * **Incorrect:** `useContext(MyContext.Consumer)` - * **Incorrect:** `useContext(MyContext.Provider)` +Un composant qui appelle `useContext` se rafraîchira toujours quand la valeur du contexte change. Si ce rafraîchissement est coûteux, vous pouvez [l’optimiser grâce à la mémoïsation](https://github.com/facebook/react/issues/15156#issuecomment-474590693). -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). - ->Tip +> Astuce > ->If you're familiar with the context API before Hooks, `useContext(MyContext)` is equivalent to `static contextType = MyContext` in a class, or to ``. +> Si vous aviez l’habitude de l’API de Contexte avant les Hooks, `useContext(MyContext)` est équivalent à `static contextType = MyContext` dans une classe, ou à ``. > ->`useContext(MyContext)` only lets you *read* the context and subscribe to its changes. You still need a `` above in the tree to *provide* the value for this context. ->>>>>>> b1bc193dbad464f7c659b10f3f57e37e265a063e +> `useContext(MyContext)` vous permet seulement de *lire* le contexte et de vous abonner à ses modifications. Vous aurez toujours besoin d’un `` plus haut dans l’arbre pour *fournir* une valeur de contexte. ## Hooks supplémentaires {#additional-hooks} @@ -377,20 +371,15 @@ function TextInputWithFocusButton() { } ``` -<<<<<<< HEAD -Remarquez que `useRef()` est utile au-delà du seul attribut `ref`. C'est [pratique pour garder des valeurs modifiables sous la main](/docs/hooks-faq.html#is-there-something-like-instance-variables), comme lorsque vous utilisez des champs d’instance dans les classes. -======= -Essentially, `useRef` is like a "box" that can hold a mutable value in its `.current` property. - -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 `
`, React will set its `.current` property to the corresponding DOM node whenever that node changes. +En gros, `useRef` est comme une « boîte » qui pourrait contenir une valeur modifiable dans sa propriété `.current`. -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. +Vous avez peut-être l'habitude d'utiliser des refs principalement pour [accéder au DOM](/docs/refs-and-the-dom.html). Si vous passez un objet ref à React avec `
`, React calera sa propriété `.current` sur le nœud DOM correspondant chaque fois que ce dernier change. -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. +Ceci dit, `useRef()` est utile au-delà du seul attribut `ref`. C'est [pratique pour garder des valeurs modifiables sous la main](/docs/hooks-faq.html#is-there-something-like-instance-variables), comme lorsque vous utilisez des champs d’instance dans les classes. -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. +Ça fonctionne parce que `useRef()` crée un objet JavaScript brut. La seule différence entre `useRef()` et la création manuelle d’un objet `{current: ... }`, c'est que `useRef` vous donnera le même objet à chaque rendu. ->>>>>>> b1bc193dbad464f7c659b10f3f57e37e265a063e +Gardez à l'esprit que `useRef` *ne vous notifie pas* quand le contenu change. Modifier la propriété `.current` n'entraîne pas un rafraîchissement. Si vous voulez exécuter du code quand React attache ou détache une ref sur un nœud DOM, vous voudrez sans doute utiliser plutôt une [ref à base de fonction de rappel](/docs/hooks-faq.html#how-can-i-measure-a-dom-node). ### `useImperativeHandle` {#useimperativehandle} @@ -422,15 +411,11 @@ Préférez l'utilisation du `useEffect` standard chaque fois que possible, pour > Astuce > -<<<<<<< HEAD -> Si vous migrez du code depuis un composant écrit à l'aide d'une classe, `useLayoutEffect` s'exécute dans la même phase que `componentDidMount` et `componentDidUpdate`. Si vous n'êtes donc pas sûr·e du Hook d'effet à utiliser, c'est probablement le moins risqué. -======= -> 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. +> Si vous migrez du code depuis un composant écrit à l'aide d'une classe, sachez que `useLayoutEffect` s'exécute dans la même phase que `componentDidMount` et `componentDidUpdate`. **Nous vous conseillons de commencer avec `useEffect`**, et de ne tenter `useLayoutEffect` que si vous rencontrez des problèmes. > ->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). +> Si vous faites du rendu côté serveur , n'oubliez pas que *ni* `useLayoutEffect` ni `useEffect` ne seront exécutés jusqu'à ce que votre code JS soit téléchargé et exécuté côté client. C’est pourquoi React vous averti quand un composant utilise `useLayoutEffect` dans le cadre d’un rendu côté serveur. Pour corriger ça, vous pouvez soit déplacer la logique dans `useEffect` (si elle n'est pas nécessaire pour le premier affichage), soit reporter l'affichage du composant jusqu'à ce que l’affichage côté client soit effectué (si le HTML aurait eu l’air cassé avant exécution du `useLayoutEffect`). > ->To exclude a component that needs layout effects from the server-rendered HTML, render it conditionally with `showChild && ` and defer showing it with `useEffect(() => { setShowChild(true); }, [])`. This way, the UI doesn't appear broken before hydration. ->>>>>>> b1bc193dbad464f7c659b10f3f57e37e265a063e +> Pour exclure un composant nécessitant des effets de mise en page *(layout effects, NdT)* du HTML généré côté serveur, vous pouvez l'afficher conditionnellement avec un `showChild && `, et différer son affichage grâce à un `useEffect(() => { setShowChild(true); }, [])`. Ainsi, l’UI ne semblera pas cassé avec son hydratation. ### `useDebugValue` {#usedebugvalue}