From d42c285aa2506902e6a1efe8264653e4a65555bc Mon Sep 17 00:00:00 2001 From: KB Date: Mon, 6 Feb 2017 17:49:36 +0100 Subject: [PATCH] [docs] Add note about refs on stateless components (#8916) * Add note about refs on stateless components * Move info about refs in the stateless components to the main section * Simplification of the part about refs and functional components * Tweaks * Move sections around * Oops * Rearrange more sections --- docs/docs/refs-and-the-dom.md | 54 ++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/docs/docs/refs-and-the-dom.md b/docs/docs/refs-and-the-dom.md index 6351d71ba69c2..eaf19e7b3912a 100644 --- a/docs/docs/refs-and-the-dom.md +++ b/docs/docs/refs-and-the-dom.md @@ -13,7 +13,19 @@ permalink: docs/refs-and-the-dom.html In the typical React dataflow, [props](/react/docs/components-and-props.html) are the only way that parent components interact with their children. To modify a child, you re-render it with new props. However, there are a few cases where you need to imperatively modify a child outside of the typical dataflow. The child to be modified could be an instance of a React component, or it could be a DOM element. For both of these cases, React provides an escape hatch. -## The ref Callback Attribute +### When to Use Refs + +There are a few good use cases for refs: + +* Managing focus, text selection, or media playback. +* Triggering imperative animations. +* Integrating with third-party DOM libraries. + +Avoid using refs for anything that can be done declaratively. + +For example, instead of exposing `open()` and `close()` methods on a `Dialog` component, pass an `isOpen` prop to it. + +### Adding a Ref to a DOM Element React supports a special attribute that you can attach to any component. The `ref` attribute takes a callback function, and the callback will be executed immediately after the component is mounted or unmounted. @@ -54,9 +66,9 @@ React will call the `ref` callback with the DOM element when the component mount Using the `ref` callback just to set a property on the class is a common pattern for accessing DOM elements. The preferred way is to set the property in the `ref` callback like in the above example. There is even a shorter way to write it: `ref={input => this.textInput = input}`. -If you worked with React before, you might be familiar with an older API where the `ref` attribute is a string, like `"textInput"`, and the DOM node is accessed as `this.refs.textInput`. We advise against it because string refs have [some issues](https://github.com/facebook/react/pull/8333#issuecomment-271648615), are considered legacy, and **are likely to be removed in one of the future releases**. If you're currently using `this.refs.textInput` to access refs, we recommend the callback pattern instead. +### Adding a Ref to a Class Component -When the `ref` attribute is used on a custom component, the `ref` callback receives the mounted instance of the component as its argument. For example, if we wanted to wrap the `CustomTextInput` above to simulate it being clicked immediately after mounting: +When the `ref` attribute is used on a custom component declared as a class, the `ref` callback receives the mounted instance of the component as its argument. For example, if we wanted to wrap the `CustomTextInput` above to simulate it being clicked immediately after mounting: ```javascript{3,9} class AutoFocusTextInput extends React.Component { @@ -73,7 +85,37 @@ class AutoFocusTextInput extends React.Component { } ``` -You may not use the `ref` attribute on functional components because they don't have instances. You can, however, use the `ref` attribute inside the functional component: +Note that this only works if `CustomTextInput` is declared as a class: + +```js{1} +class CustomTextInput extends React.Component { + // ... +} +``` + +### Refs and Functional Components + +**You may not use the `ref` attribute on functional components** because they don't have instances: + +```javascript{1,7} +function MyFunctionalComponent() { + return ; +} + +class Parent extends React.Component { + render() { + // This will *not* work! + return ( + { this.textInput = input; }} /> + ); + } +} +``` + +You should convert the component to a class if you need a ref to it, just like you do when you need lifecycle methods or state. + +You can, however, **use the `ref` attribute inside a functional component** as long as you refer to a DOM element or a class component: ```javascript{2,3,6,13} function CustomTextInput(props) { @@ -103,6 +145,10 @@ function CustomTextInput(props) { Your first inclination may be to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. See the [Lifting State Up](/react/docs/lifting-state-up.html) guide for examples of this. +### Legacy API: String Refs + +If you worked with React before, you might be familiar with an older API where the `ref` attribute is a string, like `"textInput"`, and the DOM node is accessed as `this.refs.textInput`. We advise against it because string refs have [some issues](https://github.com/facebook/react/pull/8333#issuecomment-271648615), are considered legacy, and **are likely to be removed in one of the future releases**. If you're currently using `this.refs.textInput` to access refs, we recommend the callback pattern instead. + ### Caveats If the `ref` callback is defined as an inline function, it will get called twice during updates, first with `null` and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one. You can avoid this by defining the `ref` callback as a bound method on the class, but note that it shouldn't matter in most cases.