UNPKG

ahooks

Version:
166 lines (165 loc) • 5.08 kB
import { useCallback, useRef, useState } from 'react'; import isDev from '../utils/isDev'; const useDynamicList = (initialList = []) => { const counterRef = useRef(-1); const keyList = useRef([]); const setKey = useCallback((index) => { counterRef.current += 1; keyList.current.splice(index, 0, counterRef.current); }, []); const [list, setList] = useState(() => { initialList.forEach((_, index) => { setKey(index); }); return initialList; }); const resetList = useCallback((newList) => { keyList.current = []; setList(() => { newList.forEach((_, index) => { setKey(index); }); return newList; }); }, []); const insert = useCallback((index, item) => { setList((l) => { const temp = [...l]; temp.splice(index, 0, item); setKey(index); return temp; }); }, []); const getKey = useCallback((index) => keyList.current[index], []); const getIndex = useCallback((key) => keyList.current.findIndex((ele) => ele === key), []); const merge = useCallback((index, items) => { setList((l) => { const temp = [...l]; items.forEach((_, i) => { setKey(index + i); }); temp.splice(index, 0, ...items); return temp; }); }, []); const replace = useCallback((index, item) => { setList((l) => { const temp = [...l]; temp[index] = item; return temp; }); }, []); const remove = useCallback((index) => { setList((l) => { const temp = [...l]; temp.splice(index, 1); // remove keys if necessary try { keyList.current.splice(index, 1); } catch (e) { console.error(e); } return temp; }); }, []); const batchRemove = useCallback((indexes) => { if (!Array.isArray(indexes)) { if (isDev) { console.error(`\`indexes\` parameter of \`batchRemove\` function expected to be an array, but got "${typeof indexes}".`); } return; } if (!indexes.length) { return; } setList((prevList) => { const newKeyList = []; const newList = prevList.filter((item, index) => { const shouldKeep = !indexes.includes(index); if (shouldKeep) { newKeyList.push(getKey(index)); } return shouldKeep; }); keyList.current = newKeyList; return newList; }); }, []); const move = useCallback((oldIndex, newIndex) => { if (oldIndex === newIndex) { return; } setList((l) => { const newList = [...l]; const temp = newList.filter((_, index) => index !== oldIndex); temp.splice(newIndex, 0, newList[oldIndex]); // move keys if necessary try { const keyTemp = keyList.current.filter((_, index) => index !== oldIndex); keyTemp.splice(newIndex, 0, keyList.current[oldIndex]); keyList.current = keyTemp; } catch (e) { console.error(e); } return temp; }); }, []); const push = useCallback((item) => { setList((l) => { setKey(l.length); return l.concat([item]); }); }, []); const pop = useCallback(() => { // remove keys if necessary try { keyList.current = keyList.current.slice(0, keyList.current.length - 1); } catch (e) { console.error(e); } setList((l) => l.slice(0, l.length - 1)); }, []); const unshift = useCallback((item) => { setList((l) => { setKey(0); return [item].concat(l); }); }, []); const shift = useCallback(() => { // remove keys if necessary try { keyList.current = keyList.current.slice(1, keyList.current.length); } catch (e) { console.error(e); } setList((l) => l.slice(1, l.length)); }, []); const sortList = useCallback((result) => result .map((item, index) => ({ key: index, item })) // add index into obj .sort((a, b) => getIndex(a.key) - getIndex(b.key)) // sort based on the index of table .filter((item) => !!item.item) // remove undefined(s) .map((item) => item.item), // retrive the data []); return { list, insert, merge, replace, remove, batchRemove, getKey, getIndex, move, push, pop, unshift, shift, sortList, resetList, }; }; export default useDynamicList;