react-use-services v1.0.3
react-use-services
A react module that allows users to handle shared data between components without using state. This is an attempt to move away from situations where state gets overly complex.
Motivation
State in react is a touchy subject. Through experience we found that state is best used scoped to a single component. Global state adds complexity that has resulted in the creation of many potential solutions. With this simple hook components create singleton services that can be shared amongst components.
Usage Example
This module has been created (for now) to be used with typescript. This module is also best used with the observable pattern.
To use Observables install RXJS. This is not included in the module.
npm install rxjs
// services/my-service.ts
import Service from 'react-use-services';
import { BehaviorSubject, Observable } from "rxjs";
export class MyService extends Service {
private dataItem: BehaviorSubject<number> = new BehaviorSubject(0);
public getDataItem(): Observable<number> {
return this.dataItem.asObservable();
}
public updateDataItem(value: number) {
this.dataItem.next(value);
}
}
// App.tsx
import React, { useEffect, useState } from 'react';
import { MyComponent } from './components/my-component';
import { useService } from 'react-use-services';
import { MyService } from './services/my-service';
export default function App() {
const service = useService(MyService); // here we request the service
const [thing, setThing] = useState(0);
const [showComponent, setShowComponent] = useState(false);
useEffect(() => {
// best practice is to put this inside use effect to avoid re-rendering
service.getDataItem().subscribe(setThing);
// here we update the value
service.updateDataItem(1);
}, [service])
return (
<>
<h1>
ROOT
</h1>
<p>{thing}</p>
{!showComponent && <button
onClick={() => setShowComponent(true)}
>Show Component</button>}
<hr />
{showComponent && <MyComponent />}
</>
);
}
// components/my-component
import React, { ReactElement, useEffect, useState } from 'react';
import { useService } from 'react-use-services';
import { MyService } from '../services/my-service';
export function MyComponent(): ReactElement {
const service = useService(MyService);
const [thing, setThing] = useState(0);
useEffect(() => {
// best practice is to put this inside use effect to avoid re-rendering
service.getDataItem().subscribe(setThing);
// after a delay we will set the value and see this change reflected in both components
setTimeout(() => {
service.updateDataItem(2);
}, 2000);
}, [service]);
return (
<>
<h2>
My COMPONENT
</h2>
<p>{thing}</p>
<button
// on click we will set the value and see this change reflected in both components
onClick={() => service.updateDataItem(thing + 1)}
>Click Me.</button>
</>
);
}
With the above example you can see how all components sunscribed to changes will update when the value is updated. This way users are able to manage important bits of data in dedicated services and leave state at the component level.
This is a work in progress, maybe one day this could deliver value to someone.