• The React TypeScript Cheatsheet — How To Set Up Types on Hooks React TypeScript list — How To Set Types on Hooks 🚜
  • Ibrahima Ndaw

TypeScript performs static type checking on code to make it more robust and easy to understand.

In this guide, I will show you how to use React hooks(useState, useContext, useCallback…) To set the TypeScript type

  • Set the type on useState
  • Set the type on useRef
  • Set the type on useContext
  • Set the type on the useReducer
  • Set the type on the useMemo
  • Set the type on useCallback

Let’s get started.

Set the type on useState

UseState Hook allows you to manage state in React. Equivalent to this.state in the Class component

import * as React from 'react';

export const App: React.FC = () = > {
    const [counter, setCounter] = React.useState < number > 0;

    return (
        <div className="App">
            <h1>Result: {counter}</h1>
            <button onClick={()= > setCounter(counter + 1)}>+</button>
            <button onClick={()= > setCounter(counter - 1)}>-</button>
        </div>
    );
};
Copy the code

To set the type on useState hook, you need to pass the state type to <>. If you do not have the initial state, you can use the combined type < number | null >

Set the type on useRef

The useRef hook returns a mutable ref object that allows you to access DOM elements

import * as React from 'react';

export const App: React.FC = () = > {
    const myRef = React.useRef<HTMLElement | null> (null)

    return (
        <main className="App" ref={myRef}>
            <h1>My title</h1>
        </main>
    );
};
Copy the code

As you can see, useRef receives types the same way useState does. You just need to pass it to <>. If you have more than one type, you can also use a union type

Set the type on useContext

UseContext is a hook that allows you to access and use a given Context in React.

import * as React from "react";

interface IArticle {
  id: number
  title: string
}

const ArticleContext = React.createContext<IArticle[] | []>([]);

const ArticleProvider: React.FC<React.ReactNode> = ({ children }) = > {
  const [articles, setArticles] = React.useState<IArticle[] | []>([
    { id: 1.title: "post 1" },
    { id: 2.title: "post 2"}]);return (
    <ArticleContext.Provider value={{ articles}} >
      {children}
    </ArticleContext.Provider>
  );
}

const ShowArticles: React.FC = () = > {
  const { articles } = React.useContext<IArticle[]>(ArticleContext);

  return (
    <div>
      {articles.map((article: IArticle) => (
        <p key={article.id}>{article.title}</p>
      ))}
    </div>
  );
};

export const App: React.FC = () = > {
  return (
    <ArticleProvider>
      <h1>My title</h1>
      <ShowArticles />
    </ArticleProvider>
  );
}

Copy the code
  1. The statementIArticleInterface is the type of Context,
  2. usecreateContext()Method to create a new Context and then use[]As the initial state. If you need to, you cannullUsed as an initial state.
  3. inShowArticlesGet the Context from the component and set theuseContextadmiralIArticleType array as type.

Set the type on the useReducer

The useReducer hook helps you manage more complex states. It is an alternative to useState – but remember they are different.

import * as React from "react";

enum ActionType {
  INCREMENT_COUNTER = "INCREMENT_COUNTER",
  DECREMENT_COUNTER = "DECREMENT_COUNTER"
}

interface IReducer {
  type: ActionType;
  count: number;
}

interface ICounter {
  result: number;
}

const initialState: ICounter = {
  result: 0
};

const countValue: number = 1;

const reducer: React.Reducer<ICounter, IReducer> = (state, action) = > {
  switch (action.type) {
    case ActionType.INCREMENT_COUNTER:
      return { result: state.result + action.count };
    case ActionType.DECREMENT_COUNTER:
      return { result: state.result - action.count };
    default:
      returnstate; }};export default function App() {
  const [state, dispatch] = React.useReducer<React.Reducer<ICounter, IReducer>>(
    reducer,
    initialState
  );

  return (
    <div className="App">
      <h1>Result: {state.result}</h1>
      <button
        onClick={()= >
          dispatch({ type: ActionType.INCREMENT_COUNTER, count: countValue })
        }> +
      </button>
      <button
        onClick={()= >
          dispatch({ type: ActionType.DECREMENT_COUNTER, count: countValue })
        }> -
      </button>
    </div>
  );
}

Copy the code

We start by declaring what operations the counter needs to perform (declaring them as constants). Next, we set the types for the Reducer function and the counter state, respectively

In the above code, react.reducer requires two parameters

  • aICounterThe type ofstate
  • aIReducerThe type ofaction.

Then you can start implementing the counter.

The useReducer hook takes the Reducer function and an initial state as arguments and returns two elements: the state of the counter and dispatch.

To set the type for the value returned by ueReducer, simply pass the data type to <>.

Finally, the counter can be incremented or decremented by the useReducer.

Set the type on the useMemo

The useMemo hook can remember the output of a given function, which returns a memory value

You pass in the create function and the dependency array as arguments to useMemo, which recalculates memoized values only when a dependency changes. This optimization helps avoid costly calculations every time you render. Remember that functions passed into useMemo are executed during rendering. Please do not perform non-rendering operations inside this function. Operations such as side effects are used by useEffect, not useMemo

const memoizedValue =
    React.useMemo <
    string >
    (() = > {
        computeExpensiveValue(a, b);
    },
    [a, b]);
Copy the code

To set the type on useMemo, simply pass the data type you want to remember to <>. In the code above, the hook conventions that the return value is a string.

Set the type on useCallback

The useCallback hook lets you remember functionality to prevent unnecessary rerendering. It returns a memorized callback.

Returns a Memoized callback function. Passing the inline callback function and the array of dependencies as arguments to useCallback returns the Memoized version of the callback function, which is updated only when a dependency changes. This is useful when you pass callback data to child components that are optimized and use reference equality to avoid unnecessary rendering (such as shouldComponentUpdate). UseCallback (fn, deps) is equivalent to useMemo(() => FN, deps).

type CallbackType = (. args: string[]) = > void;

const memoizedCallback =
    React.useCallback <
    CallbackType >
    (() = > {
        doSomething(a, b);
    },
    [a, b]);
Copy the code

Here, we declare CallbackType as the return value type of useCallback.

CallbackType accepts a string argument and should return a void value.

Next, we set this type on useCallback – TypeScript tells you if you pass the wrong type to a callback or dependency array.

Thanks for reading.