Aller au contenu
Logo
Image de couverture

React Hooks Personnalisés : useArray

Posté le

3 min

Nouvelle semaine, nouveau Hook à ajouter à notre collection. Dans cet épisode, nous allons implémenter le Hook useArray pour simplifier la manipulation des tableaux en React. Vous êtes prêts ? C'est parti ! 😎

Motivation

Comme à notre habitude, commençons par découvrir comment ce Hook pourra nous être utile. Pour cela, soyons originaux et prenons l'exemple d'une application To-Do list en React. Nous aurons besoin de gérer les tâches que l'utilisateur va ajouter et supprimer. Nous allons donc utiliser un tableau, et ce à l'aide du Hook useState. La fonction addTask pourrait ressembler à ceci :

1const addTask = (newTask) => {
2  setTasks(oldTasks => [...oldTasks, newTasks])
3}

Ensuite, nous aurons besoin d'une fonction removeTask, qui pourrait quant à elle ressembler à cela :

1const removeTask = (index) => {
2  setTasks(oldTasks => oldTasks.filter((_, i) => i !== index))
3}

Comme vous pouvez le constater, cela peut très vite devenir difficile à lire. Nous allons donc créer notre propre Hook useArray pour extraire cette logique au sein d'une fonction réutilisable, dans le but de simplifier notre code.

Implémentation

Tout d'abord, créons le squelette de notre Hook.

1const useArray = (initialValue = []) => {
2  const [value, setValue] = useState(initialValue)
3
4  return { value, setValue }
5}

Nous allons maintenant y créer une fonction push pour ajouter un élément à la fin de notre tableau.

1const push = element => {
2  setValue(oldValue => [...oldValue, element]);
3};

Ajoutons également la fonction remove pour supprimer l'élément à l'indice donné.

1const remove = index => {
2  setValue(oldValue => oldValue.filter((_, i) => i !== index));
3};

Il pourrait également être utile de disposer d'une fonction isEmpty pour vérifier la vacuité du tableau.

1  const isEmpty = () => value.length === 0;

En combinant toutes ces fonctions, nous obtenons notre Hook final.

1const useArray = (initialValue = []) => {
2  const [value, setValue] = useState(initialValue);
3
4  const push = element => {
5    setValue(oldValue => [...oldValue, element]);
6  };
7
8  const remove = index => {
9    setValue(oldValue => oldValue.filter((_, i) => i !== index));
10  };
11
12  const isEmpty = () => value.length === 0;
13
14  return { value, setValue, push, remove, isEmpty };
15};

Si vous manipulez de grandes quantités de données, n'hésitez-pas à optimiser ce Hook en utilisant useCallback (plus d'informations sur cet article).

Exemple :

1const push = useCallback(element => {
2  setValue(oldValue => [...oldValue, element])
3}, [])

N'hésitez-pas non plus à ajouter d'autres fonctions (comme map ou unshift) si vous en avez besoin. De manière générale, n'hésitez-pas à adapter ce Hook en fonction de vos besoins, car c'est le vôtre ! 😉

Utilisation

Revenons à notre exemple de To-Do list. En utilisant notre tout nouveau Hook, voici à quoi pourrait ressembler notre composant principal :

1const TodoList = () => {
2  const tasks = useArray([]);
3  const [newTask, setNewTask] = useState("");
4
5  // "Add" button clicked
6  const handleSubmit = e => {
7    e.preventDefault();
8    tasks.push(newTask);
9    setNewTask("");
10  };
11
12  const handleInputChange = e => setNewTask(e.target.value);
13
14  return (
15    <>
16      <h1>Todo List</h1>
17      <form onSubmit={handleSubmit}>
18        <input type="text" value={newTask} onChange={handleInputChange} />
19        <button>Add</button>
20      </form>
21      {tasks.isEmpty() ? (
22        <p>No tasks to display</p>
23      ) : (
24        <ul>
25          {tasks.value.map((task, index) => (
26            <li key={index}>
27              <input
28                type="checkbox"
29                onClick={() => tasks.remove(index)}
30                checked={false}
31              />
32              {task}
33            </li>
34          ))}
35        </ul>
36      )}
37    </>
38  );
39};

À noter que nous n'avons même plus besoin de définir des fonctions addTask et removeTask : nos méthodes tasks.push et tasks.remove sont déjà assez explicites.

Idées d'Améliorations

Pour aller plus loin, voici quelques idées d'améliorations pour enrichir ce Hook.

  • Ajouter une fonction reverse pour retourner le tableau
  • Ajouter une fonction sort pour trier le tableau
  • Ajouter une fonction clear pour vider le tableau

Conclusion

Une fois de plus, nous avons vu en quoi les Hooks personnalisés pouvaient être utiles : notre code final est plus simple, plus propre et toute la logique redondante est extraite dans une fonction à part. J'espère que ce Hook vous sera utile au sein de vos projets, et je vous dis à bientôt pour un nouveau Hook personnalisé. 👋


Code source disponible sur CodeSandbox.

Cet article t'a plu ?

N'hésite-pas à le partager sur les réseaux ! 😊

Copyright © 2022 Ludovic CHOMBEAU