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:
// Read more here: https://dirask.com/snippets/jmJNN1
//
const useProxy = (action) => {
const state = React.useMemo(
() => ({
wrapper: (...args) => {
if (state.action) {
return state.action(...args);
}
return undefined;
}
}),
[]
);
state.action = action;
return state.wrapper;
};
// ----------------------
// Read more here: https://dirask.com/snippets/D7XEop
const prependItem = (updater, item) => {
updater(array => [].concat(item, array));
};
const appendItem = (updater, item) => {
updater(array => [].concat(array, item));
};
const replaceItem = (updater, index, item) => {
updater(array => array.map((value, i) => i === index ? item : value));
};
const removeItem = (updater, index) => {
updater(array => array.filter((value, i) => i !== index));
};
// ----------------------
const useArray = (initialArray = []) => {
const [items, setItems] = React.useState(initialArray);
return {
getItems: useProxy(() => items),
setItems: useProxy((items) => setItems(items)),
prependItem: useProxy((item) => prependItem(setItems, item)),
appendItem: useProxy((item) => appendItem(setItems, item)),
replaceItem: useProxy((index, item) => replaceItem(setItems, index, item)),
removeItem: useProxy((index, item) => removeItem(setItems, index)),
isEmpty: useProxy(() => items.length === 0),
};
};
// Usage example:
const App = () => {
const array = useArray([]);
/*
const items = array.getItems(); // returns array with items
array.setItems(['a', 'b', 'c']); // replaces all array with new one
array.prependItem('prepended item'); // ads new item to the array beginning
array.appendItem('appended item'); // ads new item to the array ending
array.replaceItem(1, 'replaced item'); // replaces item that has index 1 to new one
array.removeItem(1); // removes item that has index 1
*/
...
};
Practical example
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.
// ONLINE-RUNNER:browser;
// Read more here: https://dirask.com/snippets/jmJNN1
//
const useProxy = (action) => {
const state = React.useMemo(
() => ({
wrapper: (...args) => {
if (state.action) {
return state.action(...args);
}
return undefined;
}
}),
[]
);
state.action = action;
return state.wrapper;
};
// ----------------------
// Read more here: https://dirask.com/snippets/D7XEop
const prependItem = (updater, item) => {
updater(array => [].concat(item, array));
};
const appendItem = (updater, item) => {
updater(array => [].concat(array, item));
};
const replaceItem = (updater, index, item) => {
updater(array => array.map((value, i) => i === index ? item : value));
};
const removeItem = (updater, index) => {
updater(array => array.filter((value, i) => i !== index));
};
// ----------------------
const useArray = (initialArray = []) => {
const [items, setItems] = React.useState(initialArray);
return {
getItems: useProxy(() => items),
setItems: useProxy((items) => setItems(items)),
prependItem: useProxy((item) => prependItem(setItems, item)),
appendItem: useProxy((item) => appendItem(setItems, item)),
replaceItem: useProxy((index, item) => replaceItem(setItems, index, item)),
removeItem: useProxy((index, item) => removeItem(setItems, index)),
isEmpty: useProxy(() => items.length === 0),
};
};
// ----------------------
// Usage example:
let counter = 0;
const App = () => {
const array = useArray([]);
const handlePrependClick = () => {
array.prependItem((++counter) + '-prepended');
};
const handleAppendedClick = () => {
array.appendItem((++counter) + '-appended ');
};
const items = array.getItems();
return (
<div>
<div>
<button onClick={handlePrependClick}>Prepend</button>
</div>
<br />
<pre style={{border: '1px solid silver'}}>
{items.map((item, index) => {
const handleReplaceClick = () => {
array.replaceItem(index, (++counter) + '-replaced ');
};
const handleRemoveClick = () => {
array.removeItem(index);
};
return (
<div key={item}>
<span>{item}</span>
{' '}
<button onClick={handleReplaceClick}>Replace</button>
<button onClick={handleRemoveClick}>Remove</button>
</div>
);
})}
</pre>
<br />
<div>
<button onClick={handleAppendedClick}>Append</button>
</div>
</div >
);
};
const root = document.querySelector('#root');
ReactDOM.render(<App />, root );