Implement a useArray
hook that manages an array of items with additional utility methods.
It is more convenient to use useArray
over plain useState
because in the latter case, you would always have to create a new array, mutate it, then set state to use the new array, which can be quite cumbersome.
The hook should work generically with arrays of any types.
const defaultValue = ['apple', 'banana'];export default function Component() {const { array, push, update, remove, filter, set, clear } = useArray();return (<div><p>Fruits: {array.join(', ')}</p><button onClick={() => push('orange')}>Add orange</button><button onClick={() => update(1, 'grape')}>Change second item to grape</button><button onClick={() => remove(0)}>Remove first</button><button onClick={() => filter((fruit) => fruit.includes('a'))}>Keep fruits containing 'a'</button><button onClick={() => set(defaultValue)}>Reset</button><button onClick={clear}>Clear list</button></div>);}
defaultValue
: The initial array of itemsThe hook returns an object with the following properties:
array
: The current array of itemsset: (newArray) => void
: A function that sets the array of items. This must be the same type as the setter function of useState
push: (item) => void
: A function that adds an item to the end of the arrayremove: (index: number) => void
: A function that removes an item from the array by index
filter: (predicate) => void
: A function that filters the array based on a predicate function. predicate
must be the same type as the argument of Array.prototype.filter
update: (index: number, newItem) => void
: A function that replaces an item in the array at index
clear: () => void
: A function that clears the arrayImplement a useArray
hook that manages an array of items with additional utility methods.
It is more convenient to use useArray
over plain useState
because in the latter case, you would always have to create a new array, mutate it, then set state to use the new array, which can be quite cumbersome.
The hook should work generically with arrays of any types.
const defaultValue = ['apple', 'banana'];export default function Component() {const { array, push, update, remove, filter, set, clear } = useArray();return (<div><p>Fruits: {array.join(', ')}</p><button onClick={() => push('orange')}>Add orange</button><button onClick={() => update(1, 'grape')}>Change second item to grape</button><button onClick={() => remove(0)}>Remove first</button><button onClick={() => filter((fruit) => fruit.includes('a'))}>Keep fruits containing 'a'</button><button onClick={() => set(defaultValue)}>Reset</button><button onClick={clear}>Clear list</button></div>);}
defaultValue
: The initial array of itemsThe hook returns an object with the following properties:
array
: The current array of itemsset: (newArray) => void
: A function that sets the array of items. This must be the same type as the setter function of useState
push: (item) => void
: A function that adds an item to the end of the arrayremove: (index: number) => void
: A function that removes an item from the array by index
filter: (predicate) => void
: A function that filters the array based on a predicate function. predicate
must be the same type as the argument of Array.prototype.filter
update: (index: number, newItem) => void
: A function that replaces an item in the array at index
clear: () => void
: A function that clears the arrayThe useArray
hook can be implemented by storing the array in a useState
state and defining the utility methods to manipulate the array in terms of the state's setter function with JavaScript's built-in array methods.
Remember to wrap the utility methods in useCallback
to prevent unnecessary re-renders of the calling component.
import { Dispatch, SetStateAction, useCallback, useState } from 'react';interface UseArrayReturn<T> {array: T[];set: Dispatch<SetStateAction<T[]>>;push: (element: T) => void;filter: (callback: (value: T, index: number, array: T[]) => boolean) => void;update: (index: number, newElement: T) => void;remove: (index: number) => void;clear: () => void;}export default function useArray<T>(defaultValue: T[]): UseArrayReturn<T> {const [array, setArray] = useState(defaultValue);const push: UseArrayReturn<T>['push'] = useCallback((element) => setArray((a) => [...a, element]),[],);const filter: UseArrayReturn<T>['filter'] = useCallback((callback) => setArray((a) => a.filter(callback)),[],);const update: UseArrayReturn<T>['update'] = useCallback((index, newElement) =>setArray((a) => [...a.slice(0, index),newElement,...a.slice(index + 1, a.length),]),[],);const remove: UseArrayReturn<T>['remove'] = useCallback((index) =>setArray((a) => [...a.slice(0, index), ...a.slice(index + 1, a.length)]),[],);const clear: UseArrayReturn<T>['clear'] = useCallback(() => setArray([]), []);return { array, set: setArray, push, filter, update, remove, clear };}
Ensure that the utility methods you implement modify the array in an immutable way since states in React should not be mutated.
console.log()
statements will appear here.