React Hooks Personnalisés : useArray

React Hooks Personnalisés : useArray

·

3 min read

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.

Did you find this article valuable?

Support Ludal by becoming a sponsor. Any amount is appreciated!