Posted on: February 03, 2023|Amrish Kushwaha

How to access ref from the different components in react

How to access ref from the different components in react

What is a ref?

A ref in react is an escape hatch from regular flow so that you can directly access the DOM node or rendered react component.

We can define the ref using this syntax:

const ref = React.creatRef()

When we have a ref, we normally pass it to a DOM element or React component. The react component in which we are passing the ref must be only a class component. It can never be a functional component otherwise react will throw an error.

We pass ref like this:

in DOM node

<div ref={ref}>I am div element</div>

in Class Component

<ClassComponent ref={ref} />

Once ref is passed, after the mounting of the component, that ref will point to that DOM Node in case of DOM element (you can access all of its methods and properties) or will point to the mounted state of that component in case of class component.

You can access the ref using current property.

const node = ref.current
console.log(node) // logs mounted state of component

Benefit of ref:

  • It provides a way to do the tasks which are considered an escape hatch such as accessing or focusing on the DOM node and doing the work without re-render, starting animations etc without rendering the DOM.
  • It helps in properly integrating third parties DOM library to the react application.

The drawback of ref:

It was evident that using ref in the react application is different from regular react flow as we know it from an earlier discussion. It is an escape hatch to do the task which otherwise would be too much difficult to do or have extra complexity. Overusing of ref in the project might increase complexity. So it is advisable to not overuse ref although first-time intuition would be to do everything with using ref.

There are some other drawbacks also:

  • ref is the mutable property and it can be changed from any place where current property is accessible. You will need to use it carefully.
  • Once the ref is changed, it doesn’t re-render the component which might be the bottleneck for you.

Ref in react:

When we create a ref, we pass it to either the DOM node in the current component or its child component. This flow is very intuitive because the same way we pass the props down to the child and that child may pass it to its child.

Let’s see the below example for more understanding:

Example 1:

Parent.js

import React, { useEffect } from "react"
import Child from "./Child"
const Parent = () => {
const ref = React.createRef()
useEffect(() => {
const node = ref.current
console.log(node)
}, [])
return <Child ref={ref} />
}
export default Parent

Child.js

import React from "react"
class Child extends React.Component {
render() {
return <div>I am child component</div>
}
}
export default Child

In the console, we will get the reference of the mounted child component as logged

Result

And if Child has one child named grandchild and we want to pass the ref from Parent to GrandChild, we can see that in the below example. For passing the ref from Parent to GrandChild, we will use a react feature which is called ref forwarding meaning passing the ref to the component below.

Example 2:

Parent.js

import React, { useEffect } from "react"
import Child from "./Child"
const Parent = () => {
const ref = React.createRef()
useEffect(() => {
const node = ref.current
console.log(node)
}, [])
return <Child ref={ref} />
}
export default Parent

Child.js

import React from "react"
import GrandChild from "./GrandChild"
class Child extends React.Component {
render() {
const { forwardedRef, ...rest } = this.props
return <GrandChild ref={forwardedRef} {...rest} />
}
}
export default React.forwardRef((props, ref) => {
return <Child forwardedRef={ref} {...props} />
})

or (If we want to rewrite the Child component as a functional component)

import React from "react"
import GrandChild from "./GrandChild"
const Child = React.forwardRef((props, ref) => {
return <GrandChild ref={ref} {...props} />
})
export default Child

GrandChild.js

import React from "react"
class GrandChild extends React.Component {
render() {
return <div>I am grandchild component</div>
}
}
export default GrandChild

as you can see from the above example, the ref is flowing down (like a top-down approach).

Most of the time we should follow the above approach (top-down approach) but sometimes it is a necessity to send the ref in reverse order meaning that if you have defined the ref or created the ref in the child component and you want to send it to its parent. That is also possible but with few restrictions

Access ref from different component

Here I am not referring to the normal flow (top-down approach ). I am talking about accessing ref by its parent component or by its sibling component.

We can send the ref from child to parent and through that, it's a sibling component but there is one condition → The component in which we are creating the ref, must be a CLASS COMPONENT. This approach I tested this during the writing of this blog.

Access ref from parent component:

We can access ref from the parent by sending ref as function props, we will send it as props as soon as the component is mounted.

Child.js

import React from "react"
class Child extends React.Component {
constructor(props) {
super(props)
this.ref = React.createRef()
}
componentDidMount() {
this.props.refFromChild(this.ref)
}
render() {
return <input ref={this.ref} />
}
}
export default Child

Parent.js

import React, { useState } from "react"
import Child from "./Child"
const Parent = () => {
const [childRef, setChildRef] = useState(null)
const handleRef = ref => {
setChildRef(ref)
}
const handleClick = () => {
if (childRef) {
childRef.current.focus()
}
}
return (
<>
<button onClick={handleClick}>Click</button>
<Child refFromChild={handleRef} />
</>
)
}
export default Parent

As you can see in the above example, the ref is passed to the parent from the child using refFromChild function props and it gets stored in childRef state which can be used later to perform some kind of task later such as trigger focus on input element from the parent component.

Access ref from sibling component:

Sibling components are those components whose parent is the same.

Sibling

As you can see in the above pic, Child1 and Child2 components have the same parent component (Parent1), thus these two are sibling components similarly Child3 and Child4 also have some parent (Parent2), thus these two (Child3 and Child4) are sibling components.

When we want to access ref from the sibling component, we first need to pass ref to parent from the child (in which ref is defined) and do ref forwarding to the sibling component.

Let's see that in the below example:

Child.js

import React from "react"
class Child extends React.Component {
constructor(props) {
super(props)
this.ref = React.createRef()
}
componentDidMount() {
this.props.refFromChild(this.ref)
}
render() {
return <input ref={this.ref} />
}
}
export default Child

Parent.js

import React, { useState } from "react"
import Child from "./Child"
import Sibling from "./Sibling"
const Parent = () => {
const [childRef, setChildRef] = useState(null)
const handleRef = ref => {
setChildRef(ref)
}
return (
<>
<Child refFromChild={handleRef} />
<Sibling ref={childRef} />
</>
)
}
export default Parent

Sibling.js

import React from "react"
const Sibling = React.forwardRef((props, ref) => {
const handleClick = () => {
if (ref) {
ref.current.focus()
}
}
return <button onClick={handleClick}>Click From Sibling</button>
})
export default Sibling

As you can see in the above example, the ref is created in the Child component and then passed to the Parent component using the refFromChild method which set the state childRef in the Parent component. And then the ref is forwarded to the Sibling component. Now if we click on the Click From Sibling button, it will focus on the input element in the Child component.

This is working…. wohooo…

This is all about how we can access the ref from different components (parent and sibling). Similarly, if you want to pass a ref to the multi-level parent or grandparent component or great-grandparent component, you just need to replicate the above approach. That will be super easy for you.

Thanks for reading the article. Keep coding and keep solving problems.

About author:

Amrish Kushwaha

Amrish Kushwaha

I am Amrish Kushwaha. Software Engineer, Maker, Writer. I am currently focused on frontend development with curiosity of building end to end software system. Currently I am working at Rafay Systems. I love to write as well as build side projects when I am free.

Related category articles: