Skip to Content
DocsCoding conventionsMutations and side effects

Mutations and side effects

  • Use SWR’s bound mutate  function and the mutate function from useSWRConfig() when the user performs an action that changes backend state. This keeps O3’s shared SWR cache in sync and avoids reloading the page to see changes. Prefer useSWRConfig().mutate over importing the global mutate function from swr inside components, because O3 provides its own SWR cache through the component decorator.

    There are two main approaches to mutation with SWR:

    1. Using the bound mutate  function returned by your resource hook:
    import { restBaseUrl, useOpenmrsSWR } from '@openmrs/esm-framework'; // Using bound mutate to update a specific resource 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 saved successfully') }); await closeWorkspace({ discardUnsavedChanges: true }); } catch (error) { showSnackbar({ kind: 'error', title: t('errorSavingPatient', 'Error saving patient'), subtitle: error instanceof Error ? error.message : t('unknownError', 'Unknown error'), }); } };

    useOpenmrsSWR<T> caches FetchResponse<T>, so only pass explicit data to mutate when you have the same response shape. Otherwise, revalidate the resource after a successful mutation.

    1. Using useSWRConfig().mutate for broader cache updates:
    import { restBaseUrl } from '@openmrs/esm-framework'; import { useSWRConfig } from 'swr'; const { mutate } = useSWRConfig(); // Update all cached visit resources that can show this deleted visit const handleDeleteVisit = async (patientUuid: string, visitUuid: string) => { try { await deleteVisit(visitUuid); // Update cached visit lists for this patient await mutate( (key) => typeof key === 'string' && key.startsWith(`${restBaseUrl}/visit?patient=${patientUuid}`), ); // Update the specific visit's data await mutate(`${restBaseUrl}/visit/${visitUuid}`); showSnackbar({ title: t('visitDeleted', 'Visit deleted successfully') }); } catch (error) { showSnackbar({ kind: 'error', title: t('errorDeletingVisit', 'Error deleting visit'), subtitle: error instanceof Error ? error.message : t('unknownError', 'Unknown error'), }); } };
  • When mutating data that appears in multiple places in your application, make sure to update all relevant cache entries. You can use the mutate function with a key matcher to target specific cache entries. Here’s an example of updating cohort membership data:

    const getCohortMembershipUrl = (patientUuid: string) => `${restBaseUrl}/cohortm/cohortmember?patient=${patientUuid}&v=custom:(uuid,patient:ref,cohort:(uuid,name,startDate,endDate))`; // Memoized function to update cohort membership cache const useMutateCohortMembers = (patientUuid: string) => { const { mutate } = useSWRConfig(); return useCallback(() => { const key = getCohortMembershipUrl(patientUuid); return mutate( // Only mutate cache entries that exactly match this key (cacheKey) => typeof cacheKey === 'string' && cacheKey === key ); }, [patientUuid]); };

    And here’s an example of using the mutate hook in a submit handler:

    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(); // Update the cohort membership data await mutateCohortMembers(); showSnackbar({ title: t('successfullyAdded', 'Successfully added'), kind: 'success', isLowContrast: true, subtitle: `${t('successAddPatientToList', 'Patient added to list')}: ${patientList.displayName}`, }); } catch { showSnackbar({ title: t('error', 'Error'), kind: 'error', subtitle: `${t('errorAddPatientToList', 'Patient not added to list')}: ${patientList.displayName}`, }); } }), ); } finally { closeModal(); } }, [data, selected, closeModal, t, mutateCohortMembers]);
Last updated on