DEV Community

Coder
Coder

Posted on

How to use React useRef with TypeScript

If you're a developer using React and TypeScript, you'll need to know how to use useRef to reference elements in your application. In this tutorial, we will explore how to use useRef along with TypeScript to leverage the strengths of both technologies.

What is useRef?

useRef is a React hook that provides a way to reference an element in your application, similar to the way you would with the getElementById function in vanilla JavaScript. However, useRef is more powerful because it can be used to reference any React component, not just DOM elements.

With useRef, you can preserve a value between renders without causing a re-render. This is useful for working with mutable values that don’t affect the render outcome or that would require non-reactive workarounds. By default, useRef returns a mutable object with a current property that points to the current value.

Using useRef with TypeScript

When using useRef with TypeScript, there are a few things to keep in mind. First, TypeScript requires that you specify the type of the value being referenced. Second, you need to specify the type of the component being referenced. Finally, you will likely want to specify the type of the useRef itself.

Here is an example of using useRef with TypeScript:

import React, { useRef } from 'react';

type Props = {
  text: string;
};

const MyComponent: React.FC<Props> = ({ text }) => {
  const inputEl = useRef<HTMLInputElement>(null);

  return (
    <div>
      <input type="text" ref={inputEl} />
      <p>The input value is: {inputEl.current?.value}</p>
      <p>The prop value is: {text}</p>
    </div>
  );
};

export default MyComponent;
Enter fullscreen mode Exit fullscreen mode

In this example, we defined a props type that includes a text property. The MyComponent component uses useRef to reference the input element using the HTMLInputElement type. The input reference is then used to display the input's value.

Note that we used the ? operator to access the value property. This is because the current property of useRef is initially null. The ? operator protects against null/undefined errors.

An Advanced Example

Now, let's take a look at a more advanced example that demonstrates dispatching an action with useRef and TypeScript. We will use Redux and implement a very basic counter.

First, we will create a Redux store with createSlice and configureStore:

import { createSlice, configureStore } from '@reduxjs/toolkit';
import { useDispatch } from 'react-redux';
import { useCallback, useMemo } from 'react';
import { TypedUseSelectorHook, useDispatch as useReduxDispatch, useSelector as useReduxSelector } from 'react-redux';
import { RootState } from './store';

type CounterState = {
  value: number;
};

const initialState: CounterState = {
  value: 0,
};

const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment(state) {
      state.value += 1;
    },
    decrement(state) {
      state.value -= 1;
    },
  },
});

export const { increment, decrement } = counterSlice.actions;

export const store = configureStore({
  reducer: {
    counter: counterSlice.reducer,
  },
});
Enter fullscreen mode Exit fullscreen mode

Next, we implement a counter component that renders a button and displays the current count:

import React, { useRef } from 'react';
import { useSelector } from 'react-redux';
import { RootState } from '../store';
import { increment } from '../store/counter';

const Counter = () => {
  const count = useSelector<RootState>((state) => state.counter.value);
  const dispatch = useDispatch();

  const buttonRef = useRef<HTMLButtonElement>(null);

  const handleIncrement = useCallback(() => {
    if (buttonRef.current) {
        buttonRef.current.blur();
    }
    dispatch(increment());
  }, [dispatch]);

  return (
    <div>
      <p>Count: {count}</p>
      <button type="button" onClick={handleIncrement} ref={buttonRef}>
        Increment
      </button>
    </div>
  );
};

export default Counter;
Enter fullscreen mode Exit fullscreen mode

In this example, we use useSelector to select the current count from the Redux store. We then define a handleIncrement function that uses useRef to reference the button element and update the count with dispatch. The useCallback hook ensures that the reference to the button element is not recreated on every render.

Conclusion

By now, you should have a good understanding of how to use useRef and TypeScript in your React applications. Remember, useRef allows you to reference elements and values without causing a re-render, which is useful for mutable values that don't affect the render outcome.

If you're looking to take your React and TypeScript skills to the next level, consider exploring other hooks and technologies such as Redux, React Router, and GraphQL. These technologies work seamlessly with React and TypeScript and make it even easier to build complex applications.

Top comments (0)