import {useState, useEffect} from 'react'; /** * Hook permettant d’obtenir des résultats asynchrones. * * @param initial Valeur initiale lorsque la promesse n’a pas répondu. * @param func Fonction renvoyant une promesse. * @param ...args Arguments à passer à `func` qui sont susceptibles de changer. * @return Résultats de la promesse. */ export const useAsync = (initial, func, ...args) => { const [results, setResults] = useState(initial); useEffect(() => { const fetcher = async () => { setResults(await func(...args)); }; fetcher(); }, args); return results; }; /** * Crée un état composé d’une liste et d’un élément ayant le focus dans cette * liste. À la modification de la liste ou de l’indice de l’élément ayant le * focus, la contrainte suivante est imposée : * * — si la liste n’est pas vide, focus ∈ [0, taille de la liste]. * — sinon, focus = 0. * * @return Objet contenant la liste, l’indice de l’élément ayant le focus ainsi * que des fonctions de modification. */ export const useFocusableList = () => { const [list, setList] = useState([]); const [focus, setFocus] = useState(0); return { list, focus, /** * Modifie la liste et s’assure que l’élément ayant le focus est * toujours dans sa plage de valeurs possibles. * * @param nextList Nouvelle liste. */ setList(nextList) { setList(nextList); setFocus( nextList.length === 0 ? 0 : Math.min(nextList.length - 1, focus) ); }, /** * Modifie l’élément ayant le focus en imposant les contraintes * d’intégrité. * * @param nextFocus Indice du nouvel élément ayant le focus. */ setFocus(nextFocus) { setFocus( list.length === 0 ? 0 : Math.min(list.length - 1, Math.max(0, nextFocus)) ); } }; };