Boosting UX: How I Transformed Data Management in Our App with this lib
Tags: javascript, react, typescript, frontend
Published: 2024-05-09 17:57:49

In this article, I'll talk about the time I improved the UX in software I'm currently developing at work just using this lib: [React Query (or TanStack Query)](https://tanstack.com/query/latest).

## 🚨 The Problem

In this software, we have a lot of lists and tables, being able to access the details of this data. Something like that:

![A table with an user list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz2cdf4u4t8m8h9eyatu.png)

But every time the user click on table row, goes to detail page and return to the table page, all data starts reloading...

We was using the useEffect pattern: create the request function, trigger inside an useEffect and put the data in a state. We used to create some Context too, trying to create a kind of entity hook, like useUser or useNotification.

![A loading table with an user list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1lgc94ub4712osla9w9.png)

But calm down, we already fetched this data, **how can we improve the UX?**

## 💡 The Game-Changing Solution

When I asked myself this question it coincided with the time I was studying more ways to scale frontend applications in different aspects, such as request management.

And it was the perfect match ✨: why not start to use React Query to scale the app and, at same time, improve the UX navigation?

### 🔎 How

- **Service Separation**: Before we only had the request functions inside a Context and trigger these functions inside an useEffect. But We decided to migrate API requests to a dedicated services folder, neatly organizing functionality by entity.

```javascript
const getUser = async () => {
  const user = await api.get('/user');

  return user;
};

const userService = {
  getUser,
};

export default userService;
```

- **Query creation**: We created a queries folder and put all the queries, separated by entity.

```javascript
import { useQuery } from 'react-query';

interface UseUserParams {
  userId: string
}

export const useUser = ({ userId }: UseUserParams) => {
  return useQuery({
    queryKey: ['/user', { userId }],
    queryFn: userService.getUser,
    enabled: Boolean(userId)
  });
};
```

- **Empowering Components**: With this, we can now use queries through components.

```javascript
import { useUser } from '../../api/queries/user';

const Profile = () => {
  const userId = localStorage.getItem('userId');

  const { data: user, isLoading: isUserLoading } = useUser({
    userId,
  });

  if (isUserLoading) {
    return <span>Loading...</span>;
  }

  return (
    <div>
      <span>Name: {user.name}</span>

      <span>E-mail: {user.email}</span>
    </div>
  );
};

export default Profile;
```

## ⚠️ Not Every App, Every Time

> While React Query revolutionized our UX, remember: not every application requires such finesse. Prioritize value addition, especially in MVP scenarios.

## ✅ Conclusion

With all these changes, We had some benefits:

1. **Code level**: Now we have a code that is more organized, reusable and not full of states, like isLoading or isError.

2. **UX level**: the user no longer needs to wait for new data, we show the "old" data while revalidating in the background.

As FrontEnd Engineers, our main stakeholder is the user, so if we can, we should improve the UX with code.