Data fetching made easy. Check out the new category! 🚀


useArrayState

Manages an array as a React state with built-in array manipulation methods.

useArrayState
A powerful hook for managing arrays as React state with built-in manipulation methods.

Current Array:

React ×TypeScript ×Next.js ×
3
Length
React
First
Next.js
Last
No
Empty

Add Items:

Update Item:

Array Operations:

Click on items to remove them. Use the operations above to manipulate the array.

Installation

Parameters

ParameterTypeDefaultDescription
optionsUseArrayStateOptions{}Configuration options for the hook

UseArrayStateOptions

PropertyTypeDefaultDescription
initialValueT[][]The initial array value
onChange(array: T[]) => voidnullCallback called whenever the array changes

Return Value

The hook returns an object with the following properties and methods:

PropertyTypeDescription
arrayT[]The current array state
lengthnumberThe length of the array
isEmptybooleanWhether the array is empty
firstT | undefinedThe first item in the array
lastT | undefinedThe last item in the array

Mutating Methods

MethodTypeDescription
push(...items: T[]) => voidAdds items to the end of the array
pop() => T | undefinedRemoves and returns the last item
shift() => T | undefinedRemoves and returns the first item
unshift(...items: T[]) => voidAdds items to the beginning of the array
insert(index: number, ...items: T[]) => voidInserts items at a specific index
remove(index: number) => voidRemoves item at a specific index
removeWhere(predicate: (item: T, index: number) => boolean) => voidRemoves items matching a condition
update(index: number, item: T) => voidUpdates item at a specific index
updateWhere(predicate: (item: T, index: number) => boolean, newItem: T) => voidUpdates first item matching a condition
clear() => voidRemoves all items from the array
reset() => voidResets array to initial value
setValue(newArray: T[]) => voidSets the entire array to a new value
filter(predicate: (item: T, index: number) => boolean) => voidFilters the array in place
sort(compareFn?: (a: T, b: T) => number) => voidSorts the array in place
reverse() => voidReverses the array in place

Read-only Methods

MethodTypeDescription
map<U>(transform: (item: T, index: number) => U) => U[]Maps over the array without mutating
find(predicate: (item: T, index: number) => boolean) => T | undefinedFinds the first matching item
findIndex(predicate: (item: T, index: number) => boolean) => numberFinds the index of the first matching item
includes(item: T) => booleanChecks if the array includes an item
indexOf(item: T) => numberGets the index of an item
slice(start?: number, end?: number) => T[]Returns a shallow copy of a portion

Key Features & Details

Type Safety

  • The hook is fully type-safe with TypeScript generics.
  • All methods maintain type information throughout operations.
  • Prevents runtime errors with proper type checking.

Performance Optimization

  • Uses useCallback to memoize all methods for optimal performance.
  • Prevents unnecessary re-renders by checking for actual changes.
  • Efficiently handles large arrays with immutable updates.

Change Detection

  • The onChange callback is called whenever the array state changes.
  • Changes are detected at the reference level for performance.
  • Callbacks receive the new array as their argument.

SSR Compatibility

  • Fully compatible with Server-Side Rendering.
  • No browser-specific APIs used.
  • Safe for use in Next.js and other SSR frameworks.

Examples

Basic Usage

import { useArrayState } from '@/hooks/guarahooks/use-array-state';
 
function TodoList() {
  const {
    array: todos,
    push,
    remove,
    clear,
    length,
    isEmpty,
  } = useArrayState<string>({
    initialValue: ['Learn React', 'Build an app'],
  });
 
  const addTodo = (todo: string) => {
    push(todo);
  };
 
  return (
    <div>
      <p>You have {length} todos</p>
      {isEmpty ? (
        <p>No todos yet!</p>
      ) : (
        <ul>
          {todos.map((todo, index) => (
            <li key={index}>
              {todo}
              <button onClick={() => remove(index)}>Remove</button>
            </li>
          ))}
        </ul>
      )}
      <button onClick={clear}>Clear All</button>
    </div>
  );
}

With onChange Callback

const { array, push, remove } = useArrayState<number>({
  initialValue: [1, 2, 3],
  onChange: (newArray) => {
    console.log('Array changed:', newArray);
    // Sync with localStorage, API, etc.
  },
});

Advanced Array Operations

const { array, push, filter, sort, updateWhere, removeWhere, first, last } =
  useArrayState<{ id: number; name: string; active: boolean }>({
    initialValue: [
      { id: 1, name: 'John', active: true },
      { id: 2, name: 'Jane', active: false },
    ],
  });
 
// Add new user
const addUser = (name: string) => {
  push({ id: Date.now(), name, active: true });
};
 
// Toggle user status
const toggleUser = (id: number) => {
  updateWhere((user) => user.id === id, {
    ...find((user) => user.id === id)!,
    active: !user.active,
  });
};
 
// Remove inactive users
const removeInactiveUsers = () => {
  removeWhere((user) => !user.active);
};
 
// Sort by name
const sortByName = () => {
  sort((a, b) => a.name.localeCompare(b.name));
};

Search and Filter

const {
  array: items,
  filter,
  setValue,
  reset,
} = useArrayState<string>({
  initialValue: ['apple', 'banana', 'cherry', 'date'],
});
 
const searchItems = (query: string) => {
  if (!query) {
    reset(); // Return to original list
  } else {
    filter((item) => item.toLowerCase().includes(query.toLowerCase()));
  }
};

Dynamic List Management

const {
  array: queue,
  push,
  shift,
  length,
  first,
  isEmpty,
} = useArrayState<{ id: string; message: string; timestamp: number }>();
 
// Add to queue
const enqueue = (message: string) => {
  push({
    id: crypto.randomUUID(),
    message,
    timestamp: Date.now(),
  });
};
 
// Process next item
const dequeue = () => {
  return shift();
};
 
// Queue status
const getQueueStatus = () => ({
  size: length,
  next: first,
  isEmpty,
});