UNPKG

use-array-state

Version:

Provides a reducer to simplify handling of mutations to array state

84 lines (83 loc) 3.56 kB
import { useReducer, useCallback } from 'react'; import { getType } from 'typesafe-actions'; import * as actions from './actions'; export const reducer = (state, action) => { switch (action.type) { case getType(actions.push): return [...state, action.payload]; case getType(actions.pop): return state.slice(0, state.length - 1); case getType(actions.unshift): return [action.payload, ...state]; case getType(actions.shift): return state.slice(1, state.length); case getType(actions.splice): { const nextState = [...state]; nextState.splice(...action.payload); return nextState; } case getType(actions.update): { const nextState = [...state]; nextState[action.payload.index] = action.payload.value; return nextState; } case getType(actions.set): return action.payload; case getType(actions.insert): { const nextState = [...state]; nextState.splice(action.payload.index, 0, action.payload.value); return nextState; } case getType(actions.move): { const nextState = [...state]; if (action.payload.to >= nextState.length) { let i = action.payload.to - nextState.length + 1; while (i--) { nextState.push(undefined); } } nextState.splice(action.payload.to, 0, nextState.splice(action.payload.from, 1)[0]); return nextState; } case getType(actions.remove): { const nextState = [...state]; nextState.splice(action.payload, 1); return nextState; } case getType(actions.swap): { const nextState = [...state]; const largestIndex = Math.max(...action.payload); if (largestIndex >= nextState.length) { let i = largestIndex - nextState.length + 1; while (i--) { nextState.push(undefined); } } ; [nextState[action.payload[0]], nextState[action.payload[1]]] = [ nextState[action.payload[1]], nextState[action.payload[0]] ]; return nextState; } default: return state; } }; export default function useArrayState(initialState) { const [state, dispatch] = useReducer(reducer, initialState || []); const boundActions = { push: useCallback((value) => dispatch(actions.push(value)), []), pop: useCallback(() => dispatch(actions.pop()), []), unshift: useCallback((value) => dispatch(actions.unshift(value)), []), shift: useCallback(() => dispatch(actions.shift()), []), splice: useCallback((start, deleteCount, ...args) => dispatch(actions.splice([start, deleteCount, ...args])), []), update: useCallback((index, value) => dispatch(actions.update({ index, value })), []), set: useCallback((value) => dispatch(actions.set(value)), []), insert: useCallback((index, value) => dispatch(actions.insert({ index, value })), []), move: useCallback((from, to) => dispatch(actions.move({ from, to })), []), remove: useCallback((index) => dispatch(actions.remove(index)), []), swap: useCallback((indexA, indexB) => dispatch(actions.swap([indexA, indexB])), []) }; return [state, boundActions]; }