React Refs: Key to DOM Manipulation
Tags: react, javascript, webdev, typescript
Published: 2023-10-02 17:14:30

React is a declarative UI library. A declarative? What does that mean? Let's understand the difference between imperative and declarative regarding web applications.

Let's say we wanted to create a page with a button and whenever the user types we should update the value in the Paragraph below the button. 

**In Imperative UI Programming:**

1. Create a variable to store the value of the count and assign it to 0
2. Get the button element by id
3. Get the Paragraph element by id
4. Create an on-click handler and set it as the button on-click event listener
5. In on-click handler
    1. update the count value by 1
    2. update the paragraph element textContent with the updated count.

```jsx
let count = 0;
const button = document.getElementById('button');
const paragraph = document.getElementById('paragraph');

button.onclick = function() {
  count++;
  paragraph.textContent = `Count is : ${count}`;
};

paragraph.textContent = `Count is : ${count}`;
```

{% codesandbox relaxed-khayyam-mlpwjw %}

As we can see, we are kind of instructing step by step and we are accessing the DOM elements and modifying them on our own. This can be tedious in big projects. What if we, forget to update the text content of the `paragraph` after we update the `count`?

**Declarative UI Programming (Using React ):**

1. Create a state variable named count
2. Create a handler to update the count
3. Show the count in the paragraph

```tsx
import { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  const handleCount = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <button onClick={handleCount}>Increment</button>
      <p>{`Count is : ${count}`}</p>
    </div>
  );
}
```

{% codesandbox winter-cookies-fisogu %}

In the above react program, we didn’t modify any of the DOM elements directly. We just used the API Provided by the JSX syntax, and React will take care of DOM manipulations for us.

To Summarize,

1. **In imperative programming,** we instruct the computer on how to perform each step of a task. We directly manipulate the DOM elements and update their values. It involves explicit instructions and control flow to achieve the desired outcome.
    
    
2. **In declarative programming,** we describe what we want to achieve without specifying the step-by-step instructions. We rely on abstractions and let the framework or library handle the implementation details. In the case of React, we define the desired UI structure and let React take care of updating the DOM based on the state changes.

> For more info checkout officail React Docs [Declarative UI](https://react.dev/learn/reacting-to-input-with-state#how-declarative-ui-compares-to-imperative)

So, we don’t get access to the DOM elements directly in React. What if we want to access the DOM elements? This is well handled in React, for this we have `refs`.

## What is Ref?

> In React, a Ref is a state variable that will persist values between renders. This is a special kind of state variable as it doesn’t trigger re-render when we update.
> 

We can create a Ref using `useRef` or `createRef`. We usually use `useRef` in functional Components and the `createRef` in class Components. In this blog, we will use `useRef` .

As we know react is a Declarative UI library, there is no way we can directly modify the DOM. To give access to DOM elements, React accepts a special property named `ref` on every component. 

This property accepts the `ref` value and assigns the DOM element as the current value of the `ref` object we passed.

**Syntax:**

```tsx
const countRef = useRef(0); // returns {current:0}
```

useRef accepts an initial value and returns a mutable object with the current property. This current property will hold the value.

###When to Use

1. Storing timer’s Id
2. Storing DOM elements
3. Store any value, that is not needed to trigger a re-render.


###When Not to Use 
- NEVER EVER USE Refs inside a component render. This can cause unexpected results.

Ex: let's say we have a ref name countRef and a state with color. When we update the count we will not see the updated value.
But when we change the color value it will show the latest value stored in the ref. So better we don’t use refs in the render.

{% codesandbox goofy-nobel-xbjqde %}

###DOM Manipulation using Refs.

To access the DOM elements created by React, we can use the ref property on the components. If we set this prop, react will assign the DOM element to the current value of the ref.

```jsx
export const MyComponent = ()=>{
	const inpRef = useRef(null); // creating a ref
	
	return <input ref={inputRef} /> // passing the ref as an argument, so that react will add the DOM
}
```

One day, your PO came to you and asked, can we implement scroll-to-top and scroll-to-bottom functionality on the home page. So we can scroll to the top/bottom whenever the user clicks on a button.

To achieve this we will create two buttons in the navigation bar, and when the user clicks on the button we will scroll to the top or bottom. We can do this by invoking the `scrollTo` function on the element. Let’s see this in action

We will create a ref, that will be used to store the scrollable container DOM element, and we will create two handler functions named

1. handleScrollToBottom
2. handleScrollToTop

These two functions will call the scrollTo event on the DOM element. We will pass our container Ref as a parameter to the div element that contains the text.

{% codesandbox sharp-breeze-2ne6iq %}


In the above code, we set the ref property of the div to containerRef. Whenever react sees the ref property, it will assign the DOM element to that ref’s current value.

Now we have access to the DOM element. Whenever the user clicks on those buttons we will directly modify invoke scroll to on the Text Container DOM element.

> For more info check out official : [React Docs](https://react.dev/learn/manipulating-the-dom-with-refs)

This is to access the DOM elements in the component, What if we want to access the DOM elements of another Component? We can get access to other components DOM elements using `forwardRef`.

Let’s Discuss more about `forwardRefs` and how to expose limited access to DOM elements in the next Post.

Thank you and please provide your feedback.