Refs and the DOM
Refs
A ref is an identifier that React uses to reference DOM elements
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import { Component } from 'react'
class AddColorForm extends Component {
constructor(props) {
super(props)
this.submit = this.submit.bind(this)
}
submit(e) {
const { _title, _color } = this.refs
e.preventDefault();
alert(`New Color: ${_title.value} ${_color.value}`)
_title.value = '';
_color.value = '#000000';
_title.focus();
}
render() {
return (
<form onSubmit={this.submit}>
<input ref="_title" type="text"
placeholder="color title..." required/>
<input ref="_color" type="color" required/>
<button>ADD</button>
</form>
) }
}
ReactDOM.render(<AddColorForm />, document.getElementById('root'));
React.createRef
When the ref attribute is used on an HTML element, the ref created in the constructor with React.createRef() receives the underlying DOM element as its current property
When the ref attribute is used on a custom class component, the ref object receives the mounted instance of the component as its current
Not use the ref attribute on function components because they don’t have instances
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import { Component } from 'react'
class AddColorForm extends Component {
constructor(props) {
super(props)
this.submit = this.submit.bind(this)
this._title = React.createRef();
this._color = React.createRef();
}
submit(e) {
const _title = this._title.current;
const _color = this._color.current;
e.preventDefault();
alert(`New Color: ${_title.value} ${_color.value}`)
_title.value = '';
_color.value = '#000000';
_title.focus();
}
render() {
return (
<form onSubmit={this.submit}>
<input ref={this._title} type="text"
placeholder="color title..." required/>
<input ref={this._color} type="color" required/>
<button>ADD</button>
</form>
) }
}
ReactDOM.render(<AddColorForm />, document.getElementById('root'));
import React from 'react';
import ReactDOM from 'react-dom';
class 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>
);
}
}
class AutoFocusTextInput extends React.Component {
constructor(props) {
super(props);
this.text = React.createRef();
}
componentDidMount() {
this.text.current.focusTextInput();
}
render() {
return (
<CustomTextInput ref={this.text} />
);
}
}
ReactDOM.render(<AutoFocusTextInput />, document.getElementById('root'));
Forwarding Refs
Not access to a child’s DOM node from a parent component, it breaks component encapsulation
Ref forwarding lets components opt into exposing any child component’s ref as their own
- Create a React ref by calling React.createRef and assign it to a ref variable
- Pass ref down to <Button ref={ref}> by specifying it as a JSX attribute
- React passes the ref to the (props, ref) => ... function inside forwardRef as a second argument
- Forward this ref argument down to <button ref={ref}> by specifying it as a JSX attribute
- When the ref is attached, ref.current will point to the <button> DOM node
import React from 'react';
import ReactDOM from 'react-dom';
class ButtonGroup extends React.Component {
constructor(props) {
super(props);
this.textValue = React.createRef();
}
componentDidMount() {
console.log(this.textValue.current.innerHTML);
}
render() {
return (
<div>
<Button ref = {this.textValue} />
</div>
);
}
}
const Button = React.forwardRef((props, ref) => (
<button ref={ref}>Submit</button>
))
ReactDOM.render(<ButtonGroup />, document.getElementById('root'));