(Add star to front end to improve front end skills)

英文 : joking_zhang

https://segmentfault.com/a/1190000019277029

When using React, the default way of thinking should be that we don’t force DOM changes, but instead re-render components by passing props. However, there are cases where modifying the DOM is unavoidable.

Refs in React provide a way to access React elements (or DOM nodes) created in the Render () method.

When a parent component needs to interact with a child component, we usually use props to pass the relevant information. However, in some cases, we may need to modify the subitem without re-rendering it with new props. This is where the Refs come in.

When should I use Refs?

We recommend using Refs when:

  • Integration with third-party DOM libraries

  • Trigger imperative animation

  • Manage focus, text selection or media playback

Can the third point also be interpreted as using event objects? React is a SyntheticEvent. The official documentation says: Avoid using Refs for anything that can be done with a declarative implementation.

So once we’ve determined that we really should use refs, how do we use them?

Use Refs in React

You can use Refs in a number of ways:

  • React.createRef()

  • Callback refs

  • String refs (obsolete)

  • Forwarding refs

Next, let’s look at each implementation:

React.createRef()

Refs can be created using the react.createref () function and attached to HTML elements in the React component via the ref attribute.

A REF is typically created within a component’s constructor to make it available throughout the component. Such as:

class MyComponent extends React.Component {  constructor(props) {    super(props);    this.firstRef = React.createRef();  }  render() {    return <div ref={this.firstRef} />;  }}Copy the code

As shown above:

  • A ref instance is created in the constructor and assigned to this.firstref

  • Inside the Render () method, pass the ref created in the constructor to the div

Next, let’s look at an example of using refs in the React component.

Focus input using Refs

Here’s another example:

// Ref.jsclass CustomTextInput extends React.Component {  constructor(props) {    super(props);    // create a ref to store the textInput DOM element    this.textInput = React.createRef();    this.focusTextInput = this.focusTextInput.bind(this);  }  focusTextInput() {    // Explicitly focus the text input using the raw DOM API    // Note: we're accessing "current" to get the DOM node    this.textInput.current.focus();  }  render() {    // tell React that we want to associate the <input> ref    // with the `textInput` that we created in the constructor    return (      <div>        <input type="text" ref={this.textInput} />        <input          type="button"          value="Focus the text input"          onClick={this.focusTextInput}        />      </div>    );  }}Copy the code

In the code block above, we built a button that, when clicked, automatically focuses the page on the input field.

First, we create a ref instance in the constructor, assign it to this.textinput, and then assign it to the input element via the ref attribute.

<input type="text" ref={this.textInput} />Copy the code

Note that when the ref attribute is used by an HTML element (such as the input element in the current example), the ref created using react.createref () in constructor receives the current value from the underlying DOM element.

This is a synthetical event.

This means accessing the DOM value, and we need to write something like this:

this.textInput.current;Copy the code

The second element is a button that automatically focuses on the first input box when clicked. We set the this.focusTextInput function for the onClick property.

<input  type="button"  value="Focus the text input"  onClick={this.focusTextInput}/>Copy the code

The focusTextInput() function uses JavaScript to build the standard DOM function. The.focus() method focuses the cursor on the text input box.

focusTextInput() { this.textInput.current.focus(); }Copy the code

Finally, the focusTextInput function is bound in this constructor method:

this.focusTextInput = this.focusTextInput.bind(this);Copy the code

Get the value from ref

In this example, we’ll see how to set the ref attribute for the input box and get the value from ref. The following is an example:

In this example, we create an input box to enter values. Then, when the submit button is clicked, we will read this value and print it on the console.

// Ref.jsclass CustomTextInput extends React.Component {  constructor(props) {    super(props);    // create a ref to store the textInput DOM element    this.textInput = React.createRef();  }  handleSubmit = e => {    e.preventDefault();    console.log(this.textInput.current.value);  };  render() {    // tell React that we want to associate the <input> ref    // with the `textInput` that we created in the constructor    return (      <div>        <form onSubmit={e => this.handleSubmit(e)}>          <input type="text" ref={this.textInput} />          <button>Submit</button>        </form>      </div>    );  }}Copy the code

Similarly, we use the react.createref () function to create a ref instance and assign it to the instance variable this.textinput.

In the Render function, we want to read the value of the input field under the form. How do we read this value? By specifying a ref for the input and then reading the value of ref.

<input type="text" ref={this.textInput} />Copy the code

Click the Submit button, and the form element in the above example calls the this.Handlesubmit function through the onSubmit method and prints the information in the input box on the console.

handleSubmit = e => { e.preventDefault(); console.log(this.textInput); };Copy the code

Above, the argument e contains the event object. We use e.preventDefault() to tell the browser that we are processing the clicked submit button and that we do not want the event to “bubble up” (that is, prevent the browser’s default behavior). Another difference in React is that you can’t prevent default behavior by returning false. You must explicitly use preventDefault

In the example above, we printed this.textinput, and you can see a ref object on the console.

> Object {current: HTMLInputElement}Copy the code

Notice that it has a current attribute, HTMLInputElement. This is the input DOM element itself, not the actual value. We must use this. (. Current. The value to obtain the real value of the input tag:

handleSubmit = e => { e.preventDefault(); console.log(this.textInput.current.value); };Copy the code

Using refs is a way to extract values directly from a form: just set the ref to the input tag and extract the value when you need it.

Refs callback

Refs callbacks are another way to use Refs in React. To use ref in this way, we need to set the callback function for the ref property. When we set ref, React calls this function and passes it Element as the first argument.

Here’s the code for another example. As in the above example, this code gets the text value of the input tag, but here we use a callback reference:

// Refs.jsclass CustomTextInput extends React.Component {  constructor(props) {    super(props);    this.textInput = null;    this.setTextInputRef = element => {      this.textInput = element;    };  }  handleSubmit = e => {    e.preventDefault();    console.log(this.textInput.value);  };  render() {    return (      <div>        <form onSubmit={e => this.handleSubmit(e)}>          <input type="text" ref={this.setTextInputRef} />          <button>Submit</button>        </form>      </div>    );  }}Copy the code

In the example above, we set the ref for the input tag to this.setTextInputRef.

React passes DOM elements to ref’s callback when the component is installed; When a component is unloaded, NULL is passed. (The REF callback is called before the componentDidMount and componentDidUpdate life cycle.)

String Ref (obsolete)

There is another way of setting refs, but it is considered outdated and may soon be abandoned. But you’ll probably see it in other people’s code, so here it is.

Using String refs, you’ll see an input tag like this:

<input type="text" ref="textInput" />Copy the code

Then, we can get this on a value: this. Refs. (. Value – but, again, this should not be used in the new code, because the API will be abandoned.

Forwarding Refs

Ref Forwarding is a technique for passing a Ref through a component to its children. It is useful for situations such as reusable component libraries and higher-order components (HOC).

You can use the react. forwardRef function to forward the ref to the component. Let’s look at the following example:

// Ref.jsconst TextInput = React.forwardRef((props, ref) => ( <input type="text" placeholder="Hello World" ref={ref} />)); const inputRef = React.createRef(); class CustomTextInput extends React.Component { handleSubmit = e => { e.preventDefault(); console.log(inputRef.current.value); }; render() { return ( <div> <form onSubmit={e => this.handleSubmit(e)}> <TextInput ref={inputRef} /> <button>Submit</button> </form> </div> ); }}Copy the code

Ref forwarding allows a component to receive a Ref and pass it down (in other words, “forward” it) to a child component.

In the example above, we created a component called TextInput using the input tag. So how do we pass or forward the ref to the input tag?

First, we create a ref using the following code:

const inputRef = React.createRef();Copy the code

We then pass ref down by specifying a JSX property of the same name for the component <TextInput ref={inputRef}>. React will then pass ref as the second argument to the forwardRef function.

Next, we pass this ref parameter to <input ref={ref}>. You can now access the DOM node values in the outer component via inputref.current.

Forward refs and higher-order components

Finally, let’s look at another example of using Refs, but this time using high-level components (HOC).

In the example application above, all values entered in the input tag are printed on the console. Now that we’ve set the ref attribute for the input tag, let’s look at how we need to pass/forward the ref in the higher-order component.

const Input = InputComponent => { const forwardRef = (props, ref) => { const onType = () => console.log(ref.current.value); return <InputComponent forwardedRef={ref} onChange={onType} {... props} />; }; return React.forwardRef(forwardRef); };Copy the code

There is a higher-order component called Input that takes InputComponent as an argument. As the user types, he also prints the ref value on the console.

Within the Input high-order component, the forwardRef function returns the InputComponent. The forwardRef function creates the refdref parameter. Higher-order components eventually return the wrapped component as a value.

Next, we create a component that includes the Input as a child component.

const TextInput = ({ forwardedRef, children, ... rest }) => ( <div> <input ref={forwardedRef} {... rest} /> {children} </div>);Copy the code

The above component assigns the forwardedRef to the ref property, which is received by the input box when rendering the child component. … Rest is a deconstruction of props (that is, we pass all the parameters in the REST array as props to the Input component). So how do we use the TextInput component? Like this:

const InputField = Input(TextInput); class CustomTextInput extends Component { render() { const inputRef = React.createRef(); return <InputField ref={inputRef} />; }}Copy the code

Finally, passing TextInput into the Input higher-order component returns an InputField Component.

Create a REF and pass it as a parameter to the InputField component.

conclusion

Refs is a good way to pass data to a particular subinstance, as opposed to props and State.

You have to be careful, because Refs manipulate the actual DOM, not the virtual DOM, which contradicts the React way of thinking. So, while refs should not be the default way to flow data through your application, they are a good way to read data from DOM elements when you need them.

Recommended reading

(Click on the title to jump to read)

After reading this article, you can also implement a 360 degree panorama plug-in

From Mixin to HOC to Hook

An in-depth analysis of the rendering process and features of the virtual DOM

Find this article helpful? Please share it with more people

Pay attention to “front-end daqo” plus star label, improve front-end skills

Good article, I’m reading ❤️