@react-hookz/web
Version:
React hooks done right, for browser and SSR.
96 lines (95 loc) • 4.21 kB
JavaScript
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];
}