EN
React - useArray() hook as alternative to useState() with array
0 points
In this article, we would like to show you useArray()
hook as an alternative to useState()
in JavaScript.
Quick solution:
xxxxxxxxxx
1
// Read more here: https://dirask.com/snippets/jmJNN1
2
//
3
const useProxy = (action) => {
4
const state = React.useMemo(
5
() => ({
6
wrapper: (args) => {
7
if (state.action) {
8
return state.action(args);
9
}
10
return undefined;
11
}
12
}),
13
[]
14
);
15
state.action = action;
16
return state.wrapper;
17
};
18
19
// ----------------------
20
21
// Read more here: https://dirask.com/snippets/D7XEop
22
23
const prependItem = (updater, item) => {
24
updater(array => [].concat(item, array));
25
};
26
27
const appendItem = (updater, item) => {
28
updater(array => [].concat(array, item));
29
};
30
31
const replaceItem = (updater, index, item) => {
32
updater(array => array.map((value, i) => i === index ? item : value));
33
};
34
35
const removeItem = (updater, index) => {
36
updater(array => array.filter((value, i) => i !== index));
37
};
38
39
// ----------------------
40
41
const useArray = (initialArray = []) => {
42
const [items, setItems] = React.useState(initialArray);
43
return {
44
getItems: useProxy(() => items),
45
setItems: useProxy((items) => setItems(items)),
46
prependItem: useProxy((item) => prependItem(setItems, item)),
47
appendItem: useProxy((item) => appendItem(setItems, item)),
48
replaceItem: useProxy((index, item) => replaceItem(setItems, index, item)),
49
removeItem: useProxy((index, item) => removeItem(setItems, index)),
50
isEmpty: useProxy(() => items.length === 0),
51
};
52
};
53
54
55
// Usage example:
56
57
const App = () => {
58
const array = useArray([]);
59
/*
60
const items = array.getItems(); // returns array with items
61
62
array.setItems(['a', 'b', 'c']); // replaces all array with new one
63
array.prependItem('prepended item'); // ads new item to the array beginning
64
array.appendItem('appended item'); // ads new item to the array ending
65
array.replaceItem(1, 'replaced item'); // replaces item that has index 1 to new one
66
array.removeItem(1); // removes item that has index 1
67
*/
68
69
70
};
In this example, we present how to create and use useArray()
hook as an alternative to the useState()
. We also use useProxy()
custom hook to wrap functions so they always have the same reference.
xxxxxxxxxx
1
// Read more here: https://dirask.com/snippets/jmJNN1
2
//
3
const useProxy = (action) => {
4
const state = React.useMemo(
5
() => ({
6
wrapper: (args) => {
7
if (state.action) {
8
return state.action(args);
9
}
10
return undefined;
11
}
12
}),
13
[]
14
);
15
state.action = action;
16
return state.wrapper;
17
};
18
19
// ----------------------
20
21
// Read more here: https://dirask.com/snippets/D7XEop
22
23
const prependItem = (updater, item) => {
24
updater(array => [].concat(item, array));
25
};
26
27
const appendItem = (updater, item) => {
28
updater(array => [].concat(array, item));
29
};
30
31
const replaceItem = (updater, index, item) => {
32
updater(array => array.map((value, i) => i === index ? item : value));
33
};
34
35
const removeItem = (updater, index) => {
36
updater(array => array.filter((value, i) => i !== index));
37
};
38
39
// ----------------------
40
41
const useArray = (initialArray = []) => {
42
const [items, setItems] = React.useState(initialArray);
43
return {
44
getItems: useProxy(() => items),
45
setItems: useProxy((items) => setItems(items)),
46
prependItem: useProxy((item) => prependItem(setItems, item)),
47
appendItem: useProxy((item) => appendItem(setItems, item)),
48
replaceItem: useProxy((index, item) => replaceItem(setItems, index, item)),
49
removeItem: useProxy((index, item) => removeItem(setItems, index)),
50
isEmpty: useProxy(() => items.length === 0),
51
};
52
};
53
54
// ----------------------
55
56
57
// Usage example:
58
59
let counter = 0;
60
61
const App = () => {
62
const array = useArray([]);
63
const handlePrependClick = () => {
64
array.prependItem((++counter) + '-prepended');
65
};
66
const handleAppendedClick = () => {
67
array.appendItem((++counter) + '-appended ');
68
};
69
const items = array.getItems();
70
return (
71
<div>
72
<div>
73
<button onClick={handlePrependClick}>Prepend</button>
74
</div>
75
<br />
76
<pre style={{border: '1px solid silver'}}>
77
{items.map((item, index) => {
78
const handleReplaceClick = () => {
79
array.replaceItem(index, (++counter) + '-replaced ');
80
};
81
const handleRemoveClick = () => {
82
array.removeItem(index);
83
};
84
return (
85
<div key={item}>
86
<span>{item}</span>
87
{' '}
88
<button onClick={handleReplaceClick}>Replace</button>
89
<button onClick={handleRemoveClick}>Remove</button>
90
</div>
91
);
92
})}
93
</pre>
94
<br />
95
<div>
96
<button onClick={handleAppendedClick}>Append</button>
97
</div>
98
</div >
99
);
100
};
101
102
const root = document.querySelector('#root');
103
ReactDOM.render(<App />, root );