Table of contents
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 :
const addTask = (newTask) => {
setTasks(oldTasks => [...oldTasks, newTasks])
}
Ensuite, nous aurons besoin d'une fonction removeTask
, qui pourrait quant à elle ressembler à cela :
const removeTask = (index) => {
setTasks(oldTasks => oldTasks.filter((_, i) => i !== index))
}
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.
const useArray = (initialValue = []) => {
const [value, setValue] = useState(initialValue)
return { value, setValue }
}
Nous allons maintenant y créer une fonction push
pour ajouter un élément à la fin de notre tableau.
const push = element => {
setValue(oldValue => [...oldValue, element]);
};
Ajoutons également la fonction remove
pour supprimer l'élément à l'indice donné.
const remove = index => {
setValue(oldValue => oldValue.filter((_, i) => i !== index));
};
Il pourrait également être utile de disposer d'une fonction isEmpty
pour vérifier la vacuité du tableau.
const isEmpty = () => value.length === 0;
En combinant toutes ces fonctions, nous obtenons notre Hook final.
const useArray = (initialValue = []) => {
const [value, setValue] = useState(initialValue);
const push = element => {
setValue(oldValue => [...oldValue, element]);
};
const remove = index => {
setValue(oldValue => oldValue.filter((_, i) => i !== index));
};
const isEmpty = () => value.length === 0;
return { value, setValue, push, remove, isEmpty };
};
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 :
const push = useCallback(element => { setValue(oldValue => [...oldValue, element]) }, [])
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 :
const TodoList = () => {
const tasks = useArray([]);
const [newTask, setNewTask] = useState("");
// "Add" button clicked
const handleSubmit = e => {
e.preventDefault();
tasks.push(newTask);
setNewTask("");
};
const handleInputChange = e => setNewTask(e.target.value);
return (
<>
<h1>Todo List</h1>
<form onSubmit={handleSubmit}>
<input type="text" value={newTask} onChange={handleInputChange} />
<button>Add</button>
</form>
{tasks.isEmpty() ? (
<p>No tasks to display</p>
) : (
<ul>
{tasks.value.map((task, index) => (
<li key={index}>
<input
type="checkbox"
onClick={() => tasks.remove(index)}
checked={false}
/>
{task}
</li>
))}
</ul>
)}
</>
);
};
À 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.