0.1.3 • Published 2 years ago
mobx-fetch-status v0.1.3
It is like mobx-task but with different api
use it on your own risk
better to use mobx-task
Main differences:
- status is separated from the 'task' function and can be used standalone
- default status`s state is undefined
Minimal usage
import { FetchStatus } from 'mobx-fetch-status';
const defaultStatus<undefined | 'pending' | 'fulfilled' | 'rejected'> = undefined;
const s = new FetchStatus<ErrorType>(defaultStatus);
s.empty === true;
s.set('pending');
s.set('rejected');
s.set(new Error());
s.rejected === true
s.set('fulfilled');
s.fulfilled === true
s.value // contains current status value
From promise
s = new FetchStatus();
// it`s value will change
// undefined ('empty') -> 'pending' -> 'fulfilled' || 'rejected'
const s = new FetchStatus();
let data: number;
s.fromPromise(new Promise<number>((res) => {
res(1);
// it also supports
// res(FetchStatus.promiseAction(() => {
// // executes in one transaction with status
// }))
//
}));
FetchStatus can be used as standalone solution - because you have direct control of it`s value; there is useFetchStatus for using inside react components
import { useFetchStatus } from 'mobx-fetch-status/hook';
const Component = observer(() => {
const status = useFetchStatus();
React.useEffect(() => {
status.fromPromise(...);
}, [/* mount */])
return (
<div>
status.match(...)
</div>
)
})
Can be used in class
class MyStore {
status = new FetchStatus();
@observable.ref data = [];
@action async load() {
this.status.set('pending');
try {
runInAction(() => {
this.status.set('fulfilled');
this.data = await request('/getdata');
})
} catch(e) {
this.status.set(e);
}
}
@action lessCodeLoad() { // the same as above
this.status.fromPromise(async () => {
this.data = await request('/getdata');
})
}
}
const myCompnonent = observer(() => {
const store = useInject('mystore');
return (
<div>
{store.status.match({
pending: () => <Spinner />,
fulfilled: () => <MyData data={store.data} />
})}
</div>
)
});
fetchStatusFn
same as task from mobx-task (api differ)
class Store {
// { autoload: false, capture: false } - optional
load = fetchStatusFn({ autoload: false, capture: false }, () => {
return request('/data');
})
}
if (store.load.status.empty) {
const data = await store.load(); // {capture: false} will throw Errors
}
store.load.status.value === 'fulfilled';
store.load.status.fulfilled === true;
store.load.status.match({fulfilled: () => 'ran'});
// if status.empty will execute load()
const data = await store.load.autoload();
// otherwise will return store.load.result
autoload
load = fetchStatusFn({autoload: true}, () => {})
using key autoload and calling status
will trigger store.load.autoload()
and if status.empty will be executed store.load()
class Store {
load = fetchStatusFn({ autoload: true }, () => {
return request('/data');
})
}
// store.load() calling on next line
store.load.status.match(...)
FetchStatusGroup
import { FetchStatusGroup } from 'mobx-fetch-status';
const g = new FetchStatusGroup(new FetchStatus(), new FetchStatus())
class store {
loadA = fetchStatusFn()
loadB = fetchStatusFn()
summaryStatus = loadA.status.combine(loadB.status) // new FetchStatuGroup(loadA.status, loadB.status);
}
store.summaryStatus.match(...)
Updates
- added FetchStatus.toPromise()
- added useFetchStatusForSuspense(status: FetchStatus)