Managing array state in React with custom hooks
Tags: javascript, react, hooks, webdev
Published: 2023-05-06 15:42:54

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`](https://github.com/harmyderoman/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:

```bash
npm install reactivous

# or

yarn add reactivous
```

Import `useArray` from the package:

```js
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
```

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:

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

function clearState() {
  setState([])
}

function resetState() {
  setState(['apple', 'banana'])
}
```

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:

```js
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
```

## Conclusion

[`Reactivous`](https://github.com/harmyderoman/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](https://twitter.com/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](https://vitejs.dev/) and [Vitest](https://vitest.dev/) to build and test projects.