@uphillhealth/react-service-provider
v1.1.20
Published
UpHill Health library proving service abstraction for react applications using Axios and TanStack Query
Downloads
352
Readme
lib-ts-react-service-provider
aka react-service-provider
Installation
npm install --save-dev @uphillhealth/lib-ts-react-service-provider@latest @tanstack/react-query@latest axios@latest
Verify the minimal versions of react
, react-dom
, @tanstack/react-query
and axios
at package.json peerDependencies
.
Service class
Provides request
and useQuery
abstractions.
Service.request
Abstracts an axios.request
that never throws if the request occurs to fail, it is already handled internally.
It returns a customized response that you can see below:
interface ServiceResponse<ResponseData> {
data?: ResponseData;
error?: AxiosError<ServiceResponseError>;
headers?: AxiosResponseHeaders | RawAxiosResponseHeaders;
status?: number;
}
Service.useQuery
Abstract react-query.useQuery
with an axios.request
as queryFn
to be used as a hook at react components.
It returns the generic type provided as its data.
In the case that the request fails it returns
AxiosError<ServiceResponseError>
data structure for both abstractions.interface ServiceResponseError { additionalInformation: string | null; constraints: Record<string, string>; error: string; errorNumber: number; status: number; statusMessage: string; timeStamp: number; }
Service.useMutation
Abstract react-query.useMutation
with an axios.request
as mutationFn
to be used as a hook at react components.
It returns the generic type provided as its data.
In the case that the request fails it returns
AxiosError<ServiceResponseError>
data structure for both abstractions.interface ServiceResponseError { additionalInformation: string | null; constraints: Record<string, string>; error: string; errorNumber: number; status: number; statusMessage: string; timeStamp: number; }
Creating a new service
import { Service } from '@uphillhealth/react-service-provider';
interface GetJourneyResponse {
pathwayId: string
}
interface PutPatientSessionRequestData {
language: string
}
export class PatientSessionService extends Service {
// using request abstraction
public putPatientSession(data: PutPatientSessionRequestData) {
return this.request<unknown, PutPatientSessionRequestData>({
data,
method: 'PUT',
url: `/patient-session/[institutionId]/[pathwayId]/[journeyId]`,
});
}
// The usage would be:
// PatientSessionService.putPatientSession().then(({ data, error, headers, status }) => { if(error){} else{} })
// or
// const { data, error, headers, status } = await PatientSessionService.putPatientSession()
// using useQuery abstraction
public useGetJourney() {
return this.useQuery<GetJourneyResponse>({
method: 'GET',
url: `/patient-session/[institutionId]/[pathwayId]/[journeyId]`,
});
}
// The usage would be:
// const { data, error, isLoading } = PatientSessionService.useGetJourney()
}
export class SmsReceiverService extends Service {
// using useMutation abstraction using abstracted data only
public usePostJourney() {
return this.useMutation<unknown, { comment: string }>({
method: 'PUT',
url: '/interactions/[institutionId]/inbound-records/[inboundRecordId]/comment',
});
}
// The usage would be:
// const usePostJourney = smsReceiverService.usePostJourney()
// usePostJourney.mutate({ comment: 'lorem ipsum' })
// using useMutation abstraction using params only
public usePostJourney() {
return this.useMutation<unknown, { params: { status: 'A' | 'B' | 'C' } }, unknown>({
method: 'PUT',
url: '/interactions/[institutionId]/inbound-records/[inboundRecordId]/status',
});
}
// The usage would be:
// const usePostJourney = SmsReceiverService.usePostJourney()
// usePostJourney.mutate({ params: { status: 'A' } })
}
ServiceProvider
It handles react-query client provider and services initialization as singleton.
import { ServiceProvider } from '@uphillhealth/react-service-provider';
import { PathwayService, PatientSessionService } from '@/src/services'
export const App = () => {
const services = [PathwayService, PatientSessionService]
const serviceConfigurations: ServiceConfigurations = {
baseUrl: '/',
};
return (
<ServiceProvider
institutionId={182}
language="en" // it should be the language provided by I18n library
services={services}
serviceConfigurations={serviceConfigurations}>
<RestOfTheApp />
</ServiceProvider>
);
};
useServices hook
Access your services directly by its name.
import { useServices } from '@uphillhealth/react-service-provider';
// one service
const SomeContainer1 = (): ReactElement => {
const [patientSessionService] = useServices(PatientSessionService) as [PatientSessionService];
// you can inject service specific props that later will be replaced at url
patientSessionService.serviceProps = { journeyId, pathwayId }
const useGetJourney = patientSessionService.useGetJourney();
return (
<div />
);
};
// multiple services
const SomeContainer2 = (): ReactElement => {
const [pathwayService, patientSessionService] = useServices([PathwayService, PatientSessionService]) as [PathwayService, PatientSessionService];
// you can inject service specific props that later will be replaced at url
pathwayService.serviceProps = { pathwayId }
patientSessionService.serviceProps = { journeyId, pathwayId }
const usePathwayRead = pathwayService.usePathwayRead()
const useGetJourney = patientSessionService.useGetJourney();
return (
<div />
);
};