(useRef) Cannot assign to 'current' because it is read-only property
Tags: react, abotwrotethis
Published: 2023-04-02 01:28:02

As a developer, you’re probably already familiar with React's ability to handle changes and updates to the front-end of a website with ease. But what happens when you come across an error while using React's useRef hook? Specifically, the error that states "Cannot assign to 'current' because it is read-only property."

In this tutorial, we'll explore what this error means, how to fix it, and why it happens in the first place.

## Understanding the useRef Hook in React

The useRef hook is a new addition to React that allows you to store and modify values that live outside of the component's state. These values are persistent across renders and can also survive a component re-mount.

The useRef hook returns an object with a ‘current’ property that can hold the value you want to persist across renders. When you want to access this value, you use the ‘current’ property. You can modify the value of the ‘current’ property using the JavaScript assignment operator, ‘=’.

## How to Use the useRef Hook

To start using the useRef hook, import it from the React library using the following code:

```javascript
import { useRef } from 'react';
```

You can now use the useRef hook inside your components. Let's look at an example:

```javascript
function ExampleComponent() {
  const inputRef = useRef(null);

  function handleButtonClick() {
    inputRef.current.focus();
  }
  
  return (  
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={handleButtonClick}>Focus Input</button>
    </div>
  );
}
```

In this example, we create a component called ExampleComponent that utilizes the useRef hook. We first declare a variable named inputRef that is assigned the value returned by the useRef hook. We then create a button that, when clicked, calls the handleButtonClick function. This function sets the focus on the input element by calling the .current property of the inputRef object.

## Understanding the Error "Cannot assign to 'current' because it is read-only property"

Now that we have a basic understanding of what the useRef hook is and how to use it, let's delve into the error we're examining. 

The error "Cannot assign to 'current' because it is read-only property" occurs when you try to modify the value of the ‘current’ property using the assignment operator, ‘=’, but the ‘current’ property is marked as read-only.

The useRef hook’s ‘current’ property works slightly differently from a normal JavaScript object’s property. When you try to modify a normal object property, the assignment operator, ‘=’, sets a new value for the property. However, when you try to modify the ‘current’ property of an object returned by the useRef hook, React's implementation prevents the assignment, marking it as read-only.

## Workaround for the Error

So, how do you work around the "Cannot assign to 'current' because it is read-only property" error? There are a few ways you can tackle the issue.

### Solution 1: Create a Mutable Object

One way of working around the error is to create a mutable object and store your value inside it. You can then set the variable to the mutable object and modify the value inside it without triggering React's read-only setting. Let's see an example:

```javascript
function ExampleComponent() {
  const mutableRef = { current: null };
  const inputRef = mutableRef;

  function handleButtonClick() {
    inputRef.current.focus();
  }
  
  return (  
    <div>
      <input type="text" ref={mutableRef} />
      <button onClick={handleButtonClick}>Focus Input</button>
    </div>
  );
}
```

In this example, we create a mutable object called mutableRef that contains an empty ‘current’ property. We then assign the mutableRef object to the inputRef variable using a single equals sign, which does not trigger the read-only setting in React. Finally, we assign the mutableRef object to the input element's ref prop.

### Solution 2: Use a Wrapper Function

Another workaround is to use a wrapper function to modify the 'current' property instead of using the assignment operator. Let's see an example:

```javascript
function ExampleComponent() {
  const inputRef = useRef(null);

  function setInputRef(newValue) {
    inputRef.current = newValue;
  }

  function handleButtonClick() {
    setInputRef(document.getElementById("new-input"));
    inputRef.current.focus();
  }
  
  return (  
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={handleButtonClick}>Focus Input</button>
    </div>
  );
}
```

In this example, we create a function called setInputRef that modifies the value of the ‘current’ property using the newValue parameter. We then call setInputRef to change the ‘current’ property to the new value, and set focus to the input element using useRef.current.

## Why Does the Error Happen?

The "Cannot assign to 'current' because it is read-only property" error happens because the ‘current’ property of the object returned by the useRef hook is marked as read-only in React’s implementation. This is done to prevent “unexpected” behavior that could arise when working with persisted and mutable values across renders.

React's implementation of read-only properties is actually quite beneficial. It eliminates many potential issues that can arise from unexpectedly changing component state across renders. Therefore, while the read-only implementation may cause errors, it also prevents other problematic situations.

## Summary

React's useRef hook is a powerful tool that enables you to store and modify values that persist across renders. However, it's important to be mindful of React's implementation of the hook's read-only property. If you encounter the "Cannot assign to 'current' because it is read-only property" error, you can either create a mutable object or use a wrapper function to modify the value of the ‘current’ property.

By following the steps outlined in this tutorial, you’ll have the knowledge and skills to effectively use the useRef hook while avoiding the error that can arise when modifying the 'current' property. Happy coding!