DEV Community

Cover image for React Custom Hook: useArray
Sergey Leschev
Sergey Leschev

Posted on

React Custom Hook: useArray

In this article series, we embark on a journey through the realm of custom React hooks, discovering their immense potential for elevating your development projects. Our focus today is on the "useArray" hook, one of the many carefully crafted hooks available in the collection of React custom hooks.

Github: https://github.com/sergeyleschev/react-custom-hooks

import { useState } from "react"

export default function useArray(defaultValue) {
    const [array, setArray] = useState(defaultValue)

    function push(element) {
        setArray(a => [...a, element])
    }

    function filter(callback) {
        setArray(a => a.filter(callback))
    }

    function update(index, newElement) {
        setArray(a => [
            ...a.slice(0, index),
            newElement,
            ...a.slice(index + 1, a.length),
        ])
    }

    function remove(index) {
        setArray(a => [...a.slice(0, index), ...a.slice(index + 1, a.length)])
    }

    function clear() {
        setArray([])
    }

    return { array, set: setArray, push, filter, update, remove, clear }
}
Enter fullscreen mode Exit fullscreen mode

The useArray hook utilizes the useState hook from React to initialize and manage the array state. It returns an object with the following functions:

  • push(element): Adds the specified element to the array.
  • filter(callback): Filters the array based on the provided callback function, removing elements that don't satisfy the condition.
  • update(index, newElement): Replaces the element at the specified index with the newElement.
  • remove(index): Removes the element at the specified index from the array.
  • clear(): Clears the array, setting it to an empty array.

The advantages of using this custom hook are twofold: it simplifies the management of array states and provides a cleaner and more readable code structure. With the useArray hook, you can easily add, update, remove, filter, and clear elements in an array without dealing with complex logic.

import useArray from "./useArray"

export default function ArrayComponent() {
    const { array, set, push, remove, filter, update, clear } = useArray([
        1, 2, 3, 4, 5, 6,
    ])

    return (
        <div>
            <div>{array.join(", ")}</div>
            <button onClick={() => push(7)}>Add 7</button>
            <button onClick={() => update(1, 9)}>Change Second Element To 9</button>
            <button onClick={() => remove(1)}>Remove Second Element</button>
            <button onClick={() => filter(n => n < 3)}>
                Keep Numbers Less Than 4
            </button>
            <button onClick={() => set([1, 2])}>Set To 1, 2</button>
            <button onClick={clear}>Clear</button>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Throughout this article series, we focused on one of the gems from the collection of React custom hooks  "useArray". This hook, sourced from the "react-custom-hooks" repository, revolutionizes how we work with arrays in our React applications.

Full Version | React Custom Hooks:
https://dev.to/sergeyleschev/supercharge-your-react-projects-with-custom-hooks-pl4

Top comments (11)

Collapse
 
fjones profile image
FJones

Shouldn't all of these functions be wrapped in useCallback(..., [setArray])? Having consistent function references outside seems preferable.

Also, I'd advise against using set as a function name - collision with likely keywords.

Collapse
 
sergeyleschev profile image
Sergey Leschev

Absolutely) Wrapping these functions with useCallback would help maintain consistent function references and optimize performance.

Collapse
 
noblica profile image
Dušan Perković

Hey, nice article. I do understand what you're trying to do with this, but don't you think this is too much wrapping for something that should already be pretty straight-forward?
The only reason for adding this extra wrapping in my mind would be if you do A LOT of array manipulation in your project. And if you do, all those set states compound, and might cause more rendering issues, and then you have to wrap things in useCallback to optimize, etc.

Also, adding any library to your codebase has a maintenance price. Personally, I think it's easier to just let developers mess with an ordinary array and then set state manually, then to introduce another library to the project and increase complexity.

Collapse
 
sergeyleschev profile image
Sergey Leschev

Thanks for sharing your perspective, Dušan. Your points about the trade-offs between simplifying array manipulation and potential rendering issues due to increased state updates are valid considerations. It's important to weigh the benefits of cleaner code against the potential complexities introduced by additional libraries. Different projects may require different approaches based on their specific needs.

Collapse
 
jkhaui profile image
Jordy Lee

I understand the desire to create a hook for immutably modifying arrays with terser syntax, but IMO this implementation adds an additional layer of overhead any developer working with the code needs to understand

A more idiomatic approach could be to use a proxy object representing the array, such that any native JavaScript mutative array method (push, pop, splice, etc.) can be freely used to update the copy of the array without inadvertently causing side-effects.

One other thing that isn’t super clear to the consumer of this hook is what operations are “allowed” to be called on the returned array? E.g. is it bad to do something like array.splice()?

Collapse
 
sergeyleschev profile image
Sergey Leschev

Regarding the clarity of allowed operations, you bring up a valid concern. It might be beneficial to provide clearer documentation or comments indicating which operations are safe to use on the returned array. This would help developers understand the limitations and prevent unintended side effects.

Thanks again for your insights and constructive feedback!

Collapse
 
overflow profile image
overFlow

I’m glad I follow you .....

Collapse
 
sergeyleschev profile image
Sergey Leschev

If you have any questions or suggestions, feel free to share them with me. Happy coding!

Collapse
 
tan_jung profile image
Na Bosseu

it's pretty simple!!

Collapse
 
sergeyleschev profile image
Sergey Leschev

Indeed, the "useArray" custom hook simplifies array management in React applications.

Collapse
 
catanddog999 profile image
CatAndDog999

What's the point of this? Does it help with actual development? Encapsulated components should be triggered based on the actual scenario, not encapsulated for encapsulation's sake...