DEV Community

Roman Garmider πŸ’›πŸ’™
Roman Garmider πŸ’›πŸ’™

Posted on

Managing array state in React with custom hooks

When working with complex data, it's common to use arrays to store and manipulate collections of objects. However, managing arrays in React can be painful, especially when it comes to updating, deleting, or inserting elements.

For example, let's say you have an array of objects representing a list of users, and you want to update one of them based on user input. You need to find the index of the item to update, create a copy of the original array, update the item in the copy, and finally set the state of the original array to the updated copy. This process can be error-prone, verbose, and hard to read and understand.

To make this process simpler and more reusable, I decided to write my own custom hook called useArray. This hook must provide a set of functions to manipulate arrays of objects, including adding, updating, and deleting items.

So, I created my own package called Reactivous that includes a range of hooks and plugins designed specifically for React. I believe you may find this package helpful as well. However, we will discuss it in more detail later on.

So let's begin!

useArray

First of all, install the package:

npm install reactivous

# or

yarn add reactivous
Enter fullscreen mode Exit fullscreen mode

Import useArray from the package:

import { useArray } from 'reactivous';

function FruitsList() {
  const { state, remove, push, update } = useArray(
    ['apple', 'banana', 'orange']
  );

  return (
    <div>
      <ul>
        {state.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <button onClick={() => push('grape')}>Add Grape</button>
      <button onClick={() => remove(1)}>Remove Second Fruit</button>
      <button onClick={() => update(0, 'pineapple')}
        >Update Apple</button>
    </div>
  );
}

export default FruitsList
Enter fullscreen mode Exit fullscreen mode

In this example, we're passing an initial array of fruits to the useArray hook, which returns an object containing the current reactive state of the array (state) as well as methods to manipulate it (push, remove, and update). We're rendering the array from the state as an unordered list using the map method. Finally, we're using these methods to add a grape to the array, remove the second fruit(passing index of banana), and update the first fruit (passing index of apple and the new fruit to second argument) to a pineapple.

Additionally, this hook provides the regular setState method you are familiar with using the useState hook. So you can use it to update the state:

const { setState } = useArray(['apple', 'banana']);

function clearState() {
  setState([])
}

function resetState() {
  setState(['apple', 'banana'])
}
Enter fullscreen mode Exit fullscreen mode

So look not so difficult to implement, but what happens when you have an array of objects?

useObjectsArray

The useObjectsArray hook is designed to manage arrays of objects(or records) unlike useArray which can manage all kinds of items. It provides all the methods from useArray and two additional methods: removeAll and updateAll.
These methods are very useful when you want to find items based on their properties, and not on their index.
The removeAll method removes all objects in the array that match the given key.
The updateAll method updates all objects in the array that match the first given key with the properties of the second given object.

Here is an example of using the useObjectsArray hook in a component:

import { useObjectsArray } from 'reactivous';

function FruitsList() {
  const fruits = [
    { title: 'apple' }, 
    { title: 'banana' }, 
    { title: 'orange' }
  ]

  const { state, removeAll, push, updateAll } = useObjectsArray(fruits);

  return (
    <div>
      <ul>
        {state.map((value, index) => (
          <li key={index}>{value.title}</li>
        ))}
      </ul>
      <button onClick={() => push({ title: 'grape' })}>Add Grape</button>
      <button onClick={() => removeAll({ title: 'grape'})}>Remove All Grapes</button>
      <button onClick={() => updateAll({ title: 'apple' }, { title: 'pineapple' })}
        >Update Apple</button>
    </div>
  );
}

export default FruitsList
Enter fullscreen mode Exit fullscreen mode

Conclusion

Reactivous is a package that provides a set of custom hooks and plugins for managing state and handling common tasks in React. I hope that you find these hooks useful and that they help simplify your React development process. I'm always looking to improve my library and add new hooks, so please feel free to share your thoughts and feature requests with me.

Also follow me on Twitter at @thinkin_bot. I'll be sharing updates and new features as they're added to the library, and I'd love to hear your feedback and suggestions for future improvements.

Lastly, I want to mention that Reactivous is not only a helpful package for managing array state in React, but it also serves as a good example of using Vite and Vitest to build and test projects.

Top comments (0)