UNPKG

@react-hookz/web

Version:

React hooks done right, for browser and SSR.

96 lines (95 loc) 4.21 kB
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; import { useMemo, useRef } from 'react'; import { resolveHookState } from "../util/resolveHookState.js"; import { useRerender, useSyncedRef } from '..'; export function useList(initialList) { var initial = useSyncedRef(initialList); var list = useRef(resolveHookState(initial.current)); var rerender = useRerender(); var actions = useMemo(function () { return ({ set: function (newList) { list.current = resolveHookState(newList, list.current); rerender(); }, push: function () { var items = []; for (var _i = 0; _i < arguments.length; _i++) { items[_i] = arguments[_i]; } actions.set(function (currentList) { return __spreadArray(__spreadArray([], currentList, true), items, true); }); }, updateAt: function (index, newItem) { actions.set(function (currentList) { var listCopy = __spreadArray([], currentList, true); listCopy[index] = newItem; return listCopy; }); }, insertAt: function (index, newItem) { actions.set(function (currentList) { var listCopy = __spreadArray([], currentList, true); if (index >= listCopy.length) { listCopy[index] = newItem; } else { listCopy.splice(index, 0, newItem); } return listCopy; }); }, update: function (predicate, newItem) { actions.set(function (currentList) { return currentList.map(function (item) { return (predicate(item, newItem) ? newItem : item); }); }); }, updateFirst: function (predicate, newItem) { var indexOfMatch = list.current.findIndex(function (item) { return predicate(item, newItem); }); var NO_MATCH = -1; if (indexOfMatch > NO_MATCH) { actions.updateAt(indexOfMatch, newItem); } }, upsert: function (predicate, newItem) { var indexOfMatch = list.current.findIndex(function (item) { return predicate(item, newItem); }); var NO_MATCH = -1; if (indexOfMatch > NO_MATCH) { actions.updateAt(indexOfMatch, newItem); } else { actions.push(newItem); } }, sort: function (compareFn) { actions.set(function (currentList) { return __spreadArray([], currentList, true).sort(compareFn); }); }, filter: function (callbackFn, thisArg) { /* We're implementing filter based on the Array.prototype.filter API, thus the API is not going to change, and we can turn off the no-array-callback-reference rule. Also, the filter API requires the thisArg, so we can turn off the no-array-method-this-argument-rule. */ // eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument actions.set(function (currentList) { return __spreadArray([], currentList, true).filter(callbackFn, thisArg); }); }, removeAt: function (index) { actions.set(function (currentList) { var listCopy = __spreadArray([], currentList, true); if (index < listCopy.length) { listCopy.splice(index, 1); } return listCopy; }); }, clear: function () { return actions.set([]); }, reset: function () { return actions.set(__spreadArray([], resolveHookState(initial.current), true)); }, }); }, [initial, rerender]); return [list.current, actions]; }