UNPKG

recoil-toolkit

Version:
109 lines 5.02 kB
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