Mutations et effets secondaires
-
Utilisez la fonction mutate liée de SWR et la fonction
mutateretournée paruseSWRConfig()lorsque l’utilisateur effectue une action qui change l’état du backend. Cela garde le cache SWR partagé d’O3 synchronisé et évite de recharger la page pour voir les changements. PréférezuseSWRConfig().mutateà l’import de la fonction globalemutatedepuisswrdans les composants, car O3 fournit son propre cache SWR via le décorateur de composant.Il y a deux approches principales pour la mutation avec SWR :
- Utilisation de la fonction mutate liée retournée par votre hook de ressource :
import { restBaseUrl, useOpenmrsSWR } from '@openmrs/esm-framework'; // Utilisation de mutate liée pour mettre à jour une ressource spécifique const patientUrl = `${restBaseUrl}/patient/${patientUuid}`; const { mutate } = useOpenmrsSWR<Patient>(patientUrl); const handleSave = async (updates: Partial<Patient>) => { try { await savePatient(updates); await mutate(); showSnackbar({ title: t('patientSaved', 'Patient enregistré avec succès') }); await closeWorkspace({ discardUnsavedChanges: true }); } catch (error) { showSnackbar({ kind: 'error', title: t('errorSavingPatient', 'Erreur lors de l'enregistrement du patient'), subtitle: error instanceof Error ? error.message : t('unknownError', 'Erreur inconnue'), }); } };useOpenmrsSWR<T>met en cacheFetchResponse<T>. Ne passez donc des données explicites àmutateque lorsque vous avez la même forme de réponse. Sinon, revalidez la ressource après une mutation réussie.- Utilisation de
useSWRConfig().mutatepour des mises à jour de cache plus larges :
import { restBaseUrl } from '@openmrs/esm-framework'; import { useSWRConfig } from 'swr'; const { mutate } = useSWRConfig(); // Mettre à jour toutes les ressources de visite en cache qui peuvent afficher cette visite supprimée const handleDeleteVisit = async (patientUuid: string, visitUuid: string) => { try { await deleteVisit(visitUuid); // Mettre à jour les listes de visites en cache pour ce patient await mutate( (key) => typeof key === 'string' && key.startsWith(`${restBaseUrl}/visit?patient=${patientUuid}`), ); // Mettre à jour les données de la visite spécifique await mutate(`${restBaseUrl}/visit/${visitUuid}`); showSnackbar({ title: t('visitDeleted', 'Visite supprimée avec succès') }); } catch (error) { showSnackbar({ kind: 'error', title: t('errorDeletingVisit', 'Erreur lors de la suppression de la visite'), subtitle: error instanceof Error ? error.message : t('unknownError', 'Erreur inconnue'), }); } }; -
Lors de la mutation de données qui apparaissent à plusieurs endroits dans votre application, assurez-vous de mettre à jour toutes les entrées de cache pertinentes. Vous pouvez utiliser la fonction
mutateavec un matcher de clé pour cibler des entrées de cache spécifiques. Voici un exemple de mise à jour des données d’adhésion à une cohorte :const getCohortMembershipUrl = (patientUuid: string) => `${restBaseUrl}/cohortm/cohortmember?patient=${patientUuid}&v=custom:(uuid,patient:ref,cohort:(uuid,name,startDate,endDate))`; // Fonction mémorisée pour mettre à jour le cache d'adhésion à la cohorte const useMutateCohortMembers = (patientUuid: string) => { const { mutate } = useSWRConfig(); return useCallback(() => { const key = getCohortMembershipUrl(patientUuid); return mutate( // Ne muter que les entrées de cache qui correspondent exactement à cette clé (cacheKey) => typeof cacheKey === 'string' && cacheKey === key ); }, [patientUuid]); };Et voici un exemple d’utilisation du hook mutate dans un gestionnaire de soumission :
const handleSubmit = useCallback(async () => { try { await Promise.all( selected.map(async (selectedId) => { const patientList = data.find((list) => list.id === selectedId); if (!patientList) { return; } try { await patientList.addPatient(); // Mettre à jour les données d'adhésion à la cohorte await mutateCohortMembers(); showSnackbar({ title: t('successfullyAdded', 'Ajouté avec succès'), kind: 'success', isLowContrast: true, subtitle: `${t('successAddPatientToList', 'Patient ajouté à la liste')}: ${patientList.displayName}`, }); } catch { showSnackbar({ title: t('error', 'Erreur'), kind: 'error', subtitle: `${t('errorAddPatientToList', 'Patient non ajouté à la liste')}: ${patientList.displayName}`, }); } }), ); } finally { closeModal(); } }, [data, selected, closeModal, t, mutateCohortMembers]);