suspense-datasource
v0.0.5
Published
React Suspense compatible state management solution to segregate application and UI data.
Downloads
34
Maintainers
Readme
Suspense Datasource
suspense-datasource is a library that aims to be a more organized way to store and manage backend originated application data in React. It helps the developer to separate application logic state from UI state, and also provide primitives to manage this externally loaded data.
It is made to be used in conjunction with <Suspense> where it provides a get(key) function to load the dataset that can be passed directly into a component in the Suspense's component context.
How to use it
To define a new externally loaded dataset first you need to create a class that extends the class Datasource and in the newly created class override the fetch(key) method with the instructions to make the network calls to fetch your data.
The magic happens when you define your specific methods inside your class to manipulate your state, concentrating your business rules in a place separated from the UI definition.
There's also a reset(key) method to reset the data contained under that key and reset() to reset all the data.
Example
Here's a simple example on how to use it where a datasource is defined with a cache invalidation rule that makes the fetched data expire after 10 seconds.
The class definition:
export class AlbumDatasource extends Datasource {
async fetch(key){
const albums = getAlbums(`/${key}/albums`);
setTimeout(() => {
this.reset(key)
}, 10_000)
return albums;
}
}Then it is added as an operation inside the context:
const RootContext = createContext(null);
const albumDatasource = new AlbumDatasource();
function getAlbums(artistId) {
return albumDatasource.get(artistId);
}
export function ContextProvider(props) {
return (
<RootContext.Provider
value={{
getAlbums
}}
>
{props.children}
</RootContext.Provider>
);
}
export function useProvider() {
const maybeContext = useContext(RootContext);
if (!maybeContext) throw new Error("invalid application context");
return maybeContext;
}And how you would call it inside the UI code:
export default function Albums({artist}) {
const provider = useProvider();
return (
<ul>
{provider.getAlbums(artist.id).map(album => (
<li key={album.id}>
{album.title} ({album.year})
</li>
))}
</ul>
);
}export default function ArtistPage({ artist }) {
return (
<>
<h1>{artist.name}</h1>
<Suspense fallback={<Loading />}>
<Albums artist={artist}/>
</Suspense>
</>
);
}