Refs in React, basic objects
Tags: react, javascript
Published: 2019-03-26 19:50:42

---
title: Refs in React, basic objects
description: Refs in React are basic objects.
tags: react,javascript
canonical_url: https://nickymeuleman.netlify.com/blog/react-refs/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/73lga60f5g808xt5z8im.jpg
published: true
---

<!-- Cover photo of two reference monitors. A funny joke, as you will undoubtedly agree. -->


> TL;DR: Refs are simple objects of the form `{ current: //something }`. In function components, pick `useRef`, otherwise, pick `createRef`.

In React, a ref is an object with a mutable `current` property.
That's it. You can view the [implementations](#implementations) below but they boil down to this:
`ref = { current: //something }`  
That `current` property is often set to hold a _reference_ to a DOM Element, like an `<audio>`tag

Getting a reference to an element allows you to directly give it commands.
This is useful for controlling media playback, managing focus and more.

It might be tempting to do this everywhere, but [resist](https://reactjs.org/docs/refs-and-the-dom.html#dont-overuse-refs) that temptation.

## Basic usage

The goal is to get a reference to an `<audio>`tag.
This will allow you to call `.play()` and `.pause()` on that element.

There are quite a few ways of achieving the same goal.  
The steps are always the same however.

Several examples can be viewed in this codesandbox demo
{% codesandbox 4jzlzr7937 %}

> Code shown: using createRef in a class based component with a constructor

- Create the ref object

```jsx
// inside the constructor
this.audioRef = React.createRef();
// this.audioRef = { current: null }
```

- Attach a reference to a DOM Element to that ref object

```jsx
// inside the render method
<audio ref={this.audioRef} />
// this.audioRef = { current: <audio /> }
```

- Use it

```jsx
// a handler that reacts to a click
handlePlay = () => {
  this.audioRef.play();
};
```

## Other usecases

### Referring to React Components

The examples above showed how to get a reference to a DOM Element.
That's not the only thing refs are good for. They can also point to a React Component object.

{% codesandbox 9jxqj20wqo module=%2Fsrc%2FParentComponent.js %}

Important note: you can **only** reference **class based** components this way

### Referring to a DOM Element inside a React Component

What about when you made yourself a fancy `Input` component and want a ref to point directly at the `<input>`tag so you can call `inputRef.current.focus()`?

```jsx
<Input ref={inputRef} />
```

There is a problem! It either points to the React Component object if your `Input` is a class component, or it throws a big fat error if your `Input` is a function component.

That _big fat error_ is actually really helpful:

```error
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
```

`React.forwardRef` receives a function that gets called with the props and the ref your component received. It returns what your component would normally return. There, you can attach that ref to the specific DOM Element you want.

```jsx
// in the file you want to use the ref
import Input from './Input';

function App() {
  const inputRef = React.useRef();

  // ...

  return (
    <div>
      <Input />
      {/* attach the ref to our Input component */}
      <Input ref={inputRef} />
      <Input />
    </div>
  );
}

// in your Input.js file
export default React.forwardRef((props, ref) => {
  return (
    // ...
    // forward the ref our Input component received to the HTML <input/>tag
    <input ref={ref} placeholder={props.placeholder} />
    // ...
  );
});
```

This [codesandbox demo](https://codesandbox.io/s/pyqq0o9mk7) shows three `Input` components.
One `<input />`tag is focussed through a ref a component received and forwarded using `React.forwardRef`.

Having to wrap your function component in `React.forwardRef` can become quite tedious.
In the future, this usage of `forwardRef` might become the default behaviour.
{% twitter 1109512531209584640 %}

## createRef vs. useRef

While `createRef` and `useRef` are **very** similar. There are some subtle differences.

`useRef` is a so called [hook](https://reactjs.org/docs/hooks-intro.html) and is only available in function based components.

```js
// in a function component
const myRef = React.useRef('my initial value');
```

`useRef` creates an object `{ current : initialValue }` and returns it the first time it gets called. If that object already exists, `useRef` will return that existing object instead.

`createRef` will create an object `{ current : null }` each time it is called.

```js
// in the constructor of a class based component
this.myRef = React.createRef();
// even in a function based component
const myRef = React.createRef();
```

### Instance variables

In class based components, if you want a value that can change but doesn't trigger a render cycle. An instance variable is what you want. eg: `this.palindrome = 'racecar'` and later `this.palindrome='pullup'`

In function components, `useRef` can fill that role!  
Since `useRef(initialValue)` returns an object with a mutable `current` property.
There is nothing stopping us from using it like an instance variable.

```js
const palindrome = useRef('racecar');
// const palindrome = { current: 'racecar' }
// ...
palindrome.current = 'pullup';
// const palindrome = { current: 'pullup' }
```

This demo uses `useRef` to point to the `<form>` DOM element **and** to an internal count variable.
{% codesandbox vmwxjnv433 %}

## Implementations

The implementation of both `createRef` and `useRef` in the official [React codebase](https://github.com/facebook/react) is surprisingly simple.

### createRef

```js
export function createRef() {
  const refObject = {
    current: null
  };
  if (__DEV__) {
    Object.seal(refObject);
  }
  return refObject;
}
```

The [`createRef` implementation](https://github.com/facebook/react/blob/f33e5790b83dc1ae41b2b7d59d53420e7c8383aa/packages/react/src/ReactCreateRef.js) in the React codebase

### useRef

```js
export function useRef(initialValue) {
  currentlyRenderingFiber = resolveCurrentlyRenderingFiber();
  workInProgressHook = createWorkInProgressHook();
  let ref;

  if (workInProgressHook.memoizedState === null) {
    ref = { current: initialValue };
    if (__DEV__) {
      Object.seal(ref);
    }
    workInProgressHook.memoizedState = ref;
  } else {
    ref = workInProgressHook.memoizedState;
  }
  return ref;
}
```

The [`useRef` implementation](https://github.com/facebook/react/blob/8482cbe22d1a421b73db602e1f470c632b09f693/packages/react-reconciler/src/ReactFiberHooks.js#L500-L515) in the React codebase