recoil-toolkit
Version:
109 lines • 5.02 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { useCallback, useEffect, useRef, useState } from 'react';
import { useRecoilCallback, useRecoilValue } from 'recoil';
import { uniqueId, hide, show, useRecoilCurrentSnapshot, useRecoilCurrentGetLoadable, } from '../_core';
import { lastTaskByKey, taskById, tasks, errorStack as errorStackAtom, loader, DEFAULT_LOADER, } from '../atoms';
import { TaskStatus } from '../types';
import { pushTask, updateTaskDone, updateTaskError, pushError } from '../updaters';
import { createFork } from './fork';
import { cancelTask, createCancelled, createWaitFor } from './waitFor';
export function useRecoilTask(taskCreator, deps, options) {
const optionsRef = useRef(options || {}); //options freeze
const { cancelOnUnmount, key, errorStack, loaderStack, exclusive, dataSelector, autoStart } = optionsRef.current;
if (exclusive && !key) {
throw new Error('Exclusive tasks must have a key!');
}
const [taskId, setTaskId] = useState(0);
const task = useRecoilValue(exclusive ? lastTaskByKey(key || '') : taskById(taskId));
// eslint-disable-next-line react-hooks/rules-of-hooks
const taskData = dataSelector ? useRecoilValue(dataSelector) : task === null || task === void 0 ? void 0 : task.data;
const getSnapshot = useRecoilCurrentSnapshot();
const getLoadable = useRecoilCurrentGetLoadable();
const execute = useRecoilCallback((_a) => {
var { set, snapshot } = _a, rest = __rest(_a, ["set", "snapshot"]);
return (...args) => __awaiter(this, void 0, void 0, function* () {
if (exclusive && key) {
const t = snapshot.getLoadable(lastTaskByKey(key)).getValue();
if (t && t.status === TaskStatus.Running)
return;
}
const id = uniqueId();
setTaskId(id);
const cancelled = createCancelled(id);
const waitFor = createWaitFor(cancelled);
const fork = createFork(id, Object.assign({ cancelled,
waitFor,
getSnapshot,
getLoadable,
set,
snapshot }, rest));
try {
if (loaderStack)
set(loader(loaderStack === true ? DEFAULT_LOADER : loaderStack), show);
set(tasks, pushTask({ id, options, args }));
const data = yield taskCreator(Object.assign({ fork,
cancelled,
waitFor,
getSnapshot,
getLoadable,
set,
snapshot }, rest))(...args);
set(tasks, updateTaskDone({ data, id }));
}
catch (error) {
set(tasks, updateTaskError({ error, id }));
if (errorStack) {
set(errorStackAtom, pushError({ key, error, taskId: id }));
}
}
finally {
if (loaderStack)
set(loader(loaderStack === true ? DEFAULT_LOADER : loaderStack), hide);
}
});
}, deps);
useEffect(() => {
if (autoStart) {
execute(...autoStart);
}
}, [execute]);
useEffect(() => {
if (cancelOnUnmount && taskId) {
return () => {
cancelTask(taskId);
};
}
}, [taskId]);
const resetTask = useCallback(() => {
setTaskId(0);
}, []);
return {
loading: (task === null || task === void 0 ? void 0 : task.status) === TaskStatus.Running,
execute,
error: task === null || task === void 0 ? void 0 : task.error,
data: taskData,
success: (task === null || task === void 0 ? void 0 : task.status) === TaskStatus.Done,
taskId,
resetTask,
};
}
//# sourceMappingURL=useRecoilTask.js.map