Gathering detailed insights and metrics for react-services-locator
Gathering detailed insights and metrics for react-services-locator
npm install react-services-locator
Typescript
Module System
Min. Node Version
Node Version
NPM Version
67
Supply Chain
94.5
Quality
83.1
Maintenance
100
Vulnerability
80.8
License
Verify real, reachable, and deliverable emails with instant MX records, SMTP checks, and disposable email detection.
Total Downloads
600
Last Day
1
Last Week
6
Last Month
15
Last Year
600
Minified
Minified + Gzipped
Latest Version
1.0.1
Package Id
react-services-locator@1.0.1
Unpacked Size
147.95 kB
Size
44.18 kB
File Count
11
NPM Version
10.2.3
Node Version
20.10.0
Published on
Jan 22, 2025
Cumulative downloads
Total Downloads
Last Day
0%
1
Compared to previous day
Last Week
200%
6
Compared to previous week
Last Month
-96.8%
15
Compared to previous month
Last Year
0%
600
Compared to previous year
23
A very simple (yet effective) implementation of the service locator pattern for React 18+ using Hooks, Context API
This utility is a simple service locator for React applications.
This is a simple service locator for React, my goals while building this library were:
You can directly copy and paste the code from the src
folder into your project and start using it. The code is designed to be simple and easy to read.
If you're not convinced, you can install it via npm:
Of course, you can install it via npm:
1npm install react-services-locator
Create a service by extending the AbstractBaseService
class:
1import { AbstractBaseService, ServicesResolver } from 'react-services-locator' 2export class DataService extends AbstractBaseService { 3 constructor(provider: ServicesResolver) { 4 super(provider); 5 } 6 getData(url) { 7 // fetch data from the url 8 } 9}
Note that the class should extend the AbstractBaseService
class and have a constructor that receives the ServicesResolver
as an argument.
ServiceLocatorProvider
Add the ServiceLocatorProvider
to the root of your application:
1import React from 'react'; 2 3import { ServiceLocatorProvider } from 'react-services-locator'; 4 5<ServicesProvider 6 services={[DataService]}> 7 <Consumer /> 8</ServicesProvider>
In your components, use the useService
hook to get the service instance:
1import { useService } from 'react-services-locator' 2 3export const Consumer = () => { 4 const dataService = useService(DataService); 5 6 const [data, setData] = useState(null); 7 8 useEffect(() => { 9 dataService.getData('https://getmydata.com').then((data) => { 10 setData(data); 11 }); 12 }, []); 13 14 return <div> 15 {data} 16 </div>; 17};
The purpose of the service locator is to allow services to depend on other services.
To demonstrate this, let's create a new service that depends on the DataService
:
1import { DataService } from './dataService'; 2import { AbstractBaseService } from 'react-services-locator' 3export class ProfileDataService extends AbstractBaseService { 4 constructor(provider: ServicesResolver) { 5 super(provider); 6 } 7 8 async getProphileData() { 9 // use this servicesProvider.getService to get other services 10 const dataService = this.servicesProvider.getService(DataService) 11 dataService.getData('https://getmydata.com/prohile'); 12 } 13}
Notice the AbstractBaseService
class has a servicesProvider
property that you can use to get other services.
This property is injected by the ServiceLocatorProvider
, and has only one method: getService
.
As you can see, the ProfileDataService
depends on the DataService
service.
This is not classic Dependency Injection, but it's close enough:
The main difference is that it's lazy-loaded, so you don't have to worry about the order of the services.
[!IMPORTANT] This also means you can't use get Other services inside the service class constructor. Because the services are not yet registered.
Add the ProfileDataService
to the ServiceLocatorProvider
:
1import React from 'react'; 2import { ServicesProvider } from 'react-services-locator'; 3 4<ServicesProvider 5 services={[DataService,ProfileDataService]}> 6 <Consumer /> 7</ServicesProvider>
And use the hook in the Consumer
component:
1export const Consumer = () => { 2 const [dataService, prophileDataService] = useService([DataService,ProfileDataService]); 3 4 const [data, setData] = useState(null); 5 const [prophileData, setProphileData] = useState(null); 6 useEffect(() => { 7 dataService.getData('https://getmydata.com').then((data) => { 8 setData(data); 9 }); 10 prophileDataService.getProphileData().then((data) => { 11 setProphileData(data); 12 }); 13 }, []); 14 15 return <div> 16 {data} 17 {prophileData} 18 </div>; 19};
You can use the ServiceLocatorProvider
to provide a different service implementation for testing purposes:
1import React from 'react'; 2import { ServicesProvider } from 'react-services-locator'; 3 4export class MockDataService extends AbstractBaseService { 5 constructor(provider: ServicesResolver) { 6 super(provider); 7 } 8 getData(url) { 9 return Promise.resolve('mocked data'); 10 } 11} 12// for testing purposes 13<ServicesProvider 14 services={[{ provide: DataService, useClass : MockDataService },ProfileDataService]}> 15 <Consumer /> 16</ServicesProvider>
In this example, the DataService
service is replaced with the MockDataService
service.
The Consumer component will now use the MockDataService
service instead of the DataService
service.
You can use a factory function to create a service instance, this can be useful when you need to pass arguments to the service constructor:
1import React from 'react'; 2import { ServicesProvider } from 'react-services-locator'; 3 4export class HttpService extends AbstractBaseService { 5 constructor(provider: ServicesResolver, baseUrl: string) { 6 super(provider); 7 this.baseUrl = url; 8 } 9} 10 11<ServicesProvider 12 services={[{ 13 provide: HttpService, 14 useFactory: (provider) => new HttpService(provider, 'https://baseurl.com'), 15 }]}> 16 <Consumer /> 17</ServicesProvider>
[!IMPORTANT] Notice that the factory function receives the
ServicesResolver
as a first argument, so all other arguments should come after it.
You can't use get Other services inside the service class constructor. Because the services are not yet registered:
1import { DataService } from './dataService'; 2import { AbstractBaseService } from 'react-services-locator' 3export class ProfileDataService extends AbstractBaseService { 4 constructor(provider: ServicesResolver) { 5 super(provider); 6 const dataService = this.servicesProvider.getService(DataService); 7 // ❌ error: Service DataService does not exist 8 } 9}
You can use multiple service providers that some are children of others etc. But, this library was build for only one global service provider.
So if you would build something like this:
1<ServicesProvider services={[FirstService]}>> 2 <ServicesProvider 3 services={[SecondService]}> 4 <Consumer /> 5 </ServicesProvider> 6</ServicesProvider>
The Consumer
will not be able to get the second service because of how React Context works:
1export const Consumer = () => { 2 const firstService = useService(FirstService); 3 // ❌ error: Service FirstService does not exist 4 return <div> 5 6 </div>; 7};
So just use it as one global service provider.
This library was inspired by the Angular service locator and the React hooks API. And also react-service-locator library.
No vulnerabilities found.
No security vulnerabilities found.