TypeScript est un excellent langage qui permet de vérifier le type de votre code afin de le rendre plus robuste et compréhensible.
Dans ce guide, je vais vous expliquer comment définir les types TypeScript sur les Hooks de React JS comme useState, useContext, useCallback, etc.
Sorry for the interrupt!
If you're interested in learning TypeScript or React in a comprehensive way, I highly recommend these bestseller courses:
> Understanding TypeScript - 2020 Edition
> React - The Complete Guide (incl Hooks, React Router, Redux)
Allons-y
- Définir les types sur useState
- Définir les types sur useRef
- Définir les types sur useContext
- Définir les types sur useReducer
- Définir les types sur useMemo
- Définir les types lors de l'utilisationCallback
Définir les types sur useState
Le hook useState
vous permet de gérer l'état dans votre application React. C'est l'équivalent de this.state
dans un composant de classe.
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>
)
}
Pour définir des types sur le hook useState
, vous devez passer dans <>
le type de l'état. Vous pouvez également utiliser le type d'union comme ceci <nombre | null>
si vous n'avez pas défini un état initial.
Définir les types sur useRef
Le hook useRef
retourne un objet ref mutable qui permet d'accéder aux éléments DOM.
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>
)
}
Comme vous pouvez le voir, la façon dont useRef
reçoit les types est la même que le hook useState
. Vous devez juste le passer dans le <>
; et, si vous avez plusieurs annotations de type, utilisez simplement le type union comme je le fais ici.
Définir les types sur useContext
useContext
est un hook qui permet d'accéder et de consommer un contexte donné dans une application 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>
)
}
Ici, nous commençons par créer l'interface IArticle
qui est le type de notre contexte.
Ensuite, nous l'utilisons sur la méthode createContext()
pour créer un nouveau contexte, puis l'initialisons avec []
; vous pouvez également utiliser null
comme état initial si vous le souhaitez aussi.
Avec cela en place, nous pouvons maintenant gérer l'état du contexte et définir le type sur useContext
afin d'attendre un tableau de type IArticle
comme valeur.
Définir les types sur useReducer
Le hook useReducer
permet de gérer des états plus complexes. C'est une alternative à useState
; mais gardez à l'esprit qu'ils sont différents.
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:
return state
}
}
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>
)
}
Ici, nous commençons par déclarer les types d'actions qui permettent de gérer le compteur. Ensuite, nous définissons respectivement deux types pour la fonction de réduction et l'état du compteur.
Le réducteur attend un state
de type ICounter
et une action
de type IReducer
. Avec cela, le compteur peut maintenant être manipulé en conséquence.
Le hook useReducer
reçoit la fonction de réduction et un état initial comme arguments et retourne deux éléments: le state
du compteur et l'action dispatch
.
Pour définir le type des valeurs renvoyées par ueReducer
, passez simplement dans <>
le type de vos données.
Avec cela en place, le compteur peut maintenant être incrémenté ou décrémenté via useReducer
.
Définir les types sur useMemo
Le hook useMemo
vous permet de mémoriser la sortie d'une fonction donnée. Il renvoie une valeur mémorisée.
const memoizedValue = React.useMemo<string>(() => {
computeExpensiveValue(a, b)
}, [a, b])
Pour définir des types sur useMemo
, passez simplement dans <>
le type de données que vous souhaitez mémoriser.
Ici, le hook attend un string
comme valeur renvoyée.
Définir les types lors de l'utilisationCallback
Le hook useCallback
vous permet de mémoriser une fonction pour éviter des rendus inutiles. Il renvoie un callback mémorisé.
type CallbackType = (...args: string[]) => void
const memoizedCallback = React.useCallback<CallbackType>(() => {
doSomething(a, b)
}, [a, b])
Ici, nous déclarons le type CallbackType
qui est utilisé comme type sur le callback que nous voulons mémoriser.
Il s'attend à recevoir des paramètres de type string
et doit renvoyer une valeur de type void
.
Ensuite, nous définissons ce type sur useCallback
- et si vous passez un mauvais type au callback ou au tableau de dépendances - TypeScript vous criera dessus.
Merci d'avoir lu