use-array-state (use-array-state)
Manages an array as a React state with built-in array manipulation methods.
v0.1.0
Usage
import { use-array-state } from "@/hooks"1"use client";
2
3import React, { useState } from "react";
4
5import { Badge } from "@/components/ui/badge";
6import { Button } from "@/components/ui/button";
7import {
8  Card,
9  CardContent,
10  CardDescription,
11  CardFooter,
12  CardHeader,
13  CardTitle,
14} from "@/components/ui/card";
15import { Input } from "@/components/ui/input";
16
17import { useArrayState } from "@/components/hooks/use-array-state";
18
19export function UseArrayStateDemo() {
20  const [inputValue, setInputValue] = useState("");
21  const [updateIndex, setUpdateIndex] = useState("");
22  const [updateValue, setUpdateValue] = useState("");
23
24  const {
25    array,
26    length,
27    isEmpty,
28    first,
29    last,
30    push,
31    pop,
32    shift,
33    unshift,
34    insert,
35    remove,
36    update,
37    clear,
38    reset,
39    sort,
40    reverse,
41    filter,
42  } = useArrayState<string>({
43    initialValue: ["React", "TypeScript", "Next.js"],
44    onChange: (newArray) => {
45      console.log("Array changed:", newArray);
46    },
47  });
48
49  const handleAddItem = () => {
50    if (inputValue.trim()) {
51      push(inputValue.trim());
52      setInputValue("");
53    }
54  };
55
56  const handleUpdateItem = () => {
57    const index = parseInt(updateIndex);
58    if (!isNaN(index) && updateValue.trim()) {
59      update(index, updateValue.trim());
60      setUpdateIndex("");
61      setUpdateValue("");
62    }
63  };
64
65  const handleInsertAtStart = () => {
66    if (inputValue.trim()) {
67      unshift(inputValue.trim());
68      setInputValue("");
69    }
70  };
71
72  const handleRemoveItem = (index: number) => {
73    remove(index);
74  };
75
76  const handleFilterLongItems = () => {
77    filter((item) => item.length <= 6);
78  };
79
80  return (
81    <Card className="w-full max-w-2xl mx-auto">
82      <CardHeader>
83        <CardTitle>useArrayState</CardTitle>
84        <CardDescription>
85          A powerful hook for managing arrays as React state with built-in
86          manipulation methods.
87        </CardDescription>
88      </CardHeader>
89      <CardContent className="space-y-6">
90        {/* Array Display */}
91        <div>
92          <h3 className="text-sm font-medium mb-2">Current Array:</h3>
93          <div className="flex flex-wrap gap-2 min-h-[40px] p-3 border rounded-md bg-muted/20">
94            {array.map((item, index) => (
95              <Badge
96                key={index}
97                variant="secondary"
98                className="cursor-pointer hover:bg-destructive hover:text-destructive-foreground"
99                onClick={() => handleRemoveItem(index)}
100              >
101                {item} ×
102              </Badge>
103            ))}
104            {isEmpty && (
105              <span className="text-muted-foreground text-sm">
106                Array is empty
107              </span>
108            )}
109          </div>
110        </div>
111
112        {/* Array Stats */}
113        <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
114          <div className="text-center">
115            <div className="text-2xl font-bold">{length}</div>
116            <div className="text-xs text-muted-foreground">Length</div>
117          </div>
118          <div className="text-center">
119            <div className="text-sm font-medium truncate">{first || "N/A"}</div>
120            <div className="text-xs text-muted-foreground">First</div>
121          </div>
122          <div className="text-center">
123            <div className="text-sm font-medium truncate">{last || "N/A"}</div>
124            <div className="text-xs text-muted-foreground">Last</div>
125          </div>
126          <div className="text-center">
127            <div className="text-sm font-medium">{isEmpty ? "Yes" : "No"}</div>
128            <div className="text-xs text-muted-foreground">Empty</div>
129          </div>
130        </div>
131
132        <div className="border-t" />
133
134        {/* Add Items */}
135        <div className="space-y-3">
136          <h3 className="text-sm font-medium">Add Items:</h3>
137          <div className="flex gap-2">
138            <Input
139              placeholder="Enter item to add"
140              value={inputValue}
141              onChange={(e) => setInputValue(e.target.value)}
142              onKeyDown={(e) => {
143                if (e.key === "Enter") {
144                  handleAddItem();
145                }
146              }}
147            />
148            <Button onClick={handleAddItem} disabled={!inputValue.trim()}>
149              Add to End
150            </Button>
151            <Button
152              onClick={handleInsertAtStart}
153              disabled={!inputValue.trim()}
154              variant="outline"
155            >
156              Add to Start
157            </Button>
158          </div>
159        </div>
160
161        {/* Update Item */}
162        <div className="space-y-3">
163          <h3 className="text-sm font-medium">Update Item:</h3>
164          <div className="flex gap-2">
165            <Input
166              placeholder="Index"
167              value={updateIndex}
168              onChange={(e) => setUpdateIndex(e.target.value)}
169              className="w-20"
170            />
171            <Input
172              placeholder="New value"
173              value={updateValue}
174              onChange={(e) => setUpdateValue(e.target.value)}
175              onKeyDown={(e) => {
176                if (e.key === "Enter") {
177                  handleUpdateItem();
178                }
179              }}
180            />
181            <Button
182              onClick={handleUpdateItem}
183              disabled={!updateIndex.trim() || !updateValue.trim()}
184              variant="outline"
185            >
186              Update
187            </Button>
188          </div>
189        </div>
190
191        <div className="border-t" />
192
193        {/* Array Operations */}
194        <div className="space-y-3">
195          <h3 className="text-sm font-medium">Array Operations:</h3>
196          <div className="grid grid-cols-2 md:grid-cols-4 gap-2">
197            <Button
198              onClick={() => pop()}
199              disabled={isEmpty}
200              variant="outline"
201              size="sm"
202            >
203              Remove Last
204            </Button>
205            <Button
206              onClick={() => shift()}
207              disabled={isEmpty}
208              variant="outline"
209              size="sm"
210            >
211              Remove First
212            </Button>
213            <Button
214              onClick={() => sort()}
215              disabled={isEmpty}
216              variant="outline"
217              size="sm"
218            >
219              Sort A-Z
220            </Button>
221            <Button
222              onClick={() => reverse()}
223              disabled={isEmpty}
224              variant="outline"
225              size="sm"
226            >
227              Reverse
228            </Button>
229            <Button
230              onClick={handleFilterLongItems}
231              disabled={isEmpty}
232              variant="outline"
233              size="sm"
234            >
235              Filter Short
236            </Button>
237            <Button
238              onClick={clear}
239              disabled={isEmpty}
240              variant="destructive"
241              size="sm"
242            >
243              Clear All
244            </Button>
245            <Button onClick={reset} variant="outline" size="sm">
246              Reset
247            </Button>
248          </div>
249        </div>
250      </CardContent>
251      <CardFooter className="text-xs text-muted-foreground">
252        Click on items to remove them. Use the operations above to manipulate
253        the array.
254      </CardFooter>
255    </Card>
256  );
257}
258Install
npx wkkkis-hooks add use-array-stateOptions
| Name | Type | Default | Description | 
|---|---|---|---|
| — | UseArrayStateOptions | {} | Configuration options for the hook | 
| initialValue | T[] | [] | The initial array value | 
| onChange | (array: T[]) => void | null | Callback called whenever the array changes | 
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.
 
Files in this hook
| Source | Destination | 
|---|---|
| files/use-array-state.ts | src/hooks/use-array-state.ts |