In React, Ref is a way we can get hold of DOM nodes in JSX in the render method. Without this, we use the conventional document.getElementById
.
In this shot, we will learn how to use refs
to get access to DOM nodes and class instances in React.
To refer to an element in the render method of our component, we create a ref using the React.createRef
API and pass it as an attribute value to the ref
attribute.
class App extends React.Component {
componentDidMount() {
this.divRef = React.createRef()
}
render() {
return (
<div>
<div id="divR" ref={this.divRef}>App, here</div>
</div>
)
}
}
We used React.createRef
to generate a unique id ref
and pass it to divRef
. We want to get the DOM node of the div#divR
element, so we set the ref attribute and point the value to the divRef
.
With this, the DOM node of div#divR
will be contained in the current property of the divRef
: this.divRef.current
will return a DOM node of the div#divR
element.
class App extends React.Component {
componentDidMount() {
this.divRef = React.createRef()
this.divRef.current // hold the DOM node `HTMLDivElement` of the div#divR
}
render() {
return (
<div>
<div id="divR" ref={this.divRef}>App, here</div>
</div>
)
}
}
With this.divRef.current
, we can now use any DOM APIs like innerHTML
, innerValue
, etc.
Using ref
like this is synonymous to using the document.getElementById(...)
.
class App extends React.Component {
componentDidMount() {
this.divRef = document.getElementById("divR") // hold the DOM node `HTMLDivElement` of the div#divR
}
render() {
return (
<div>
<div id="divR">App, here</div>
</div>
)
}
}
Let’s see another usage:
class App extends React.Component {
constructor() {
this.state = {
data: null
}
}
componentDidMount() {
this.inputRef = React.createRef()
}
handleClick = () => {
this.setState({ data: this.inputRef.current.target.value })
}
render() {
return (
<div>
{this.state.data }
<input ref={this.inputRef} />
<button onClick={this.handleClick}> Click Me </button>
</div>
)
}
}
We have input and a button. We have state data that holds the value typed in the input box. We used ref
to get the DOM node of the input element. With the DOM node, we get the value typed in when the button is clicked.
As this.inputRef.current
holds the DOM node of the input textbox, we use the target.value
API in HTMLInputElement
to get the value typed in the input box.
React.Components
Refs can also be used to get an instance of React Components.
class TextInput extends React.Component {
constructor() {
this.inputRef = React.createRef()
}
getInputValue() {
return this.inputRef.current.target.value
}
render() {
return (
<>
<input ref={this.inputRef} />
</>
)
}
}
class App extends React.Component {
constructor() {
this.state = {
data: null
}
}
componentDidMount() {
this.textInputRef = React.createRef()
}
handleClick = () => {
this.setState({ data: this.textInputRef.current.getInputValue() })
}
render() {
return (
<div>
{this.state.data }
<TextInput ref={this.textInputRef} />
<button onClick={this.handleClick}> Click Me </button>
</div>
)
}
}
Here, we are attaching ref
to TextInput
, which is a class Component
. We will get the instance in this.textInputRef.current
. Here, we can call any methods in the TextInput
class.
Above, we used it to get the input value of the text box in the TextInput
class. The getInputValue
in the TextInput
class returns the value of the input box element. So, in App
we call the method in this.textInputRef.getInputValue()
.
Refs cannot work in functional components because they don’t have instances. Instead, the function components should be converted to class components.
function TextInput() {
this.inputRef = React.createRef()
TextInput.getInputValue = function() {
return this.inputRef.current.target.value
}
return (
<>
<input ref={this.inputRef} />
</>
)
}
class App extends React.Component {
constructor() {
this.state = {
data: null
}
}
componentDidMount() {
this.textInputRef = React.createRef()
}
handleClick = () => {
this.setState({ data: this.textInputRef.current.getInputValue() })
}
render() {
return (
<div>
{this.state.data }
<TextInput ref={this.textInputRef} />
<button onClick={this.handleClick}> Click Me </button>
</div>
)
}
}
The above won’t work because TextInput
is a functional component. Creating refs through React.createRef
in function components would work.
So, we can create and attach refs
in function components so far, as they are elements and class components.
class TextInput extends Component {
constructor() {
this.inputRef = React.createRef()
}
getInputValue = function() {
return this.inputRef.current.target.value
}
render() {
return (
<>
<input ref={this.inputRef} />
</>
)
}
}
function App(){
const [state, setState] = useState({data: null})
this.textInputRef = React.createRef()
handleClick = () => {
this.setState({ data: this.textInputRef.current.getInputValue() })
}
return (
<div>
{this.state.data }
<TextInput ref={this.textInputRef} />
<button onClick={this.handleClick}> Click Me </button>
</div>
)
}
We just learned in a simple and fast way what refs
are and how to use them.
Ref : Reactjs Blog.