# Passing ref by useContext
## What is ref in React?
**Ref is a plain JavaScript object with the current property that you can read and modify.**
Ref is designed to step outside React since it won't trigger re-render, but situations like
1. [setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout)
2. Storing and manipulating DOM elements like [scrollIntoView API]([https:/](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)/)
**which are some value and need to be stored somewhere.**
(They don’t impact the rendering logic like state, so we choose refs.)
## How to pass a ref?
Normally, we use [forwardRef()](https://react.dev/reference/react/forwardRef) to pass a ref to the parent component,
/Input.ts(children component)
```typescript
import { forwardRef } from 'react';
const ChildrenInput = forwardRef(function Input(props, ref) {
const { label, ...otherProps } = props;
return (
<label>
{label}
<input {...otherProps} ref={ref} />
</label>
);
});
export default Input;
```
/App.ts(parent component)
```typescript
import { useRef } from 'react';
import ChildrenInput from './ChildrenInput.ts';
export default function Form() {
const ref = useRef(null);
function handleClick() {
ref.current.focus();
}
return (
<form> // parent component
<ChildrenInput label="Enter your name:" ref={ref} />
<button type="button" onClick={handleClick}>
Click here to focus the ref input
</button>
</form>
);
}
```
## Passing a ref in a different way
However, when you need to develop a new feature in a large project, you may face a problem that passing a ref into other component(not the parent component) like this
```typescript
<Anchor/>
// there are dozens of components here
<Card/>
```
You are not able to pass a ref inside <Card> to <Anchor>.
To solve this problem, we can use useContext to wrap them up:
```typescript
import React, { RefObject, useState } from "react";
import Card from "./Card";
import Anchor from "./Anchor";
interface IContext {
dispatchRef: (ref: RefObject<HTMLDivElement>) => void;
scrollToRef: () => void;
}
export const StoreContext = React.createContext<IContext>({
dispatchRef: () => {},
scrollToRef: () => {},
});
const RefProvider = () => {
const [ref, setRef] = useState<RefObject<HTMLDivElement> | null>(null);
/**
* set the ref state
* @param ref Element
*/
const dispatchRef = (ref: RefObject<HTMLDivElement>) => {
setRef(ref);
};
/**
* scroll to the ref
*/
const scrollToRef = () => {
if (ref) {
ref.current?.scrollIntoView({ behavior: "smooth" });
}
};
return (
<StoreContext.Provider value={{ dispatchRef, scrollToRef }}>
<Anchor />
<Card />
</StoreContext.Provider>
);
};
export default RefProvider;
```
```typescript
import { useContext, useRef } from "react";
import { StoreContext } from "./RefProvider";
const Card = () => {
const { dispatchRef } = useContext(StoreContext);
const cardRef = useRef<HTMLDivElement>(null);
dispatchRef(cardRef);
return (
<div className="card" ref={cardRef}>
Card
</div>
);
};
export default Card;
```
```typescript
import { useContext } from "react";
import { StoreContext } from "./RefProvider";
const Anchor = () => {
const { scrollToRef } = useContext(StoreContext);
return (
<div className="anchor" onClick={scrollToRef}>
Click me to scroll to Card
</div>
);
};
export default Anchor;
```
## Conclusion
- This is just a concept of passing ref in a different way instead of forwardRef
- Please consider the structure of your project before you decide to pass a ref by useContext
- There are trade-offs like adding a new Provider is a must since it's useContext
[Demo of passing ref by useContext ](https://codesandbox.io/p/sandbox/passingrefdemo-s5rr4l?file=%2Fsrc%2FApp.css%3A23%2C15)