Are No-Code Tools A Good Choice For Developers?
Published: 2023-03-17 09:21:24

---
title: Are No-Code Tools A Good Choice For Developers?
published: true
date: 2023-02-17 12:00:00 UTC
tags: 
canonical_url: https://marmelab.com/blog/2023/02/17/build-a-react-admin-like-interface-in-no-code.html
---

Developers often use low-code tools like react-admin to increase their development speed. But what about no-code tools? How far can they get and are they nice to use?

As an experiment, I decided to try replicating the React-Admin demo using a no-code tool. This e-commerce demo shows an admin for a fictional poster shop. I chose the most popular no-code platform, Retool. My goal is to see if it is possible to replicate the functionality of a developer tool using a no-code approach. Stay tuned to see how it turns out!

![React-Admin demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fca3hz812rhls1ajnmcf.jpg)

#Working With A Fake API

Before diving into no-code, I need to set up an API that Retool can use. To do this, I have to write some code - but it's for testing purposes, and it should be the only code in this post. I use the e-commerce fake data generator published with react-admin, along with JSON Server to create the API, and ngrok to expose it.

![Code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rm53r8ckgi2n9jk174c6.png)

Now I have an API running locally and accessible from the outside via a ngrok.io URL:

![Code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6conmz3bksdfgcuvxyba.png)

#Setting Up The API Connection

To access my API in Retool, I create a new resource of type REST API using the ngrok URL. I name this resource "Posters Galore".

![Setting Up The API Connection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8i6zjbz2ap6vufy9mlaa.jpeg)

#Creating The First Component

It's time to start building the first component: the leftmost block of the top row in the demo dashboard, which displays the monthly revenue.

![First Component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zrpw43o8qcm5caui8d1j.jpg)

To begin, I create a new app in Retool and name it "Dashboard". To display data in the component, I need to set up a query that retrieves the commands for the last 30 days. I name this query "commands_for_last_30_days" and use the "Posters Galore" resource and the `commands` endpoint.

In order to filter the results to the last 30 days, I need to set the `date_gte` URL parameter. For the value, Retool allows me to use a JavaScript expression with some included libraries like `moment`. This expression will return the date 30 days ago: `{{moment().startOf('day').subtract(30, 'days')}}`.

![Commands](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ssdapkysmxejclv33ba.jpeg)

Next, I add a `Statistic` component to my app. To allow for more customization, such as changing the background color, I wrap it in a `Container` component. Using the sidebar, I can easily configure the `Statistic` component to meet my needs, such as adding a label and icon.

To set the displayed value, I select the `commands_for_last_30_days` query and use a JavaScript expression to compute the sum of the total field: `{{commands_for_last_30_days.data.reduce((acc, command) => acc + command.total, 0)}}`.

The first component that fetches the API and renders the result is now ready!

![first component that fetches the API ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b77pgct3ulqrcw5hyreu.jpeg)

I can follow the same process to create the component that displays the number of orders in the last 30 days with the following displayed value: `{{commands_for_last_30_days.data.length}}`.

#Displaying A List Of Records

The next component I want to build is the list of pending reviews.

![List Of Records](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zdwijshzkshfhp4dfcaa.jpg)

To do this, I need to create a `pending_reviews` query that retrieves all the reviews with a status of "pending". Then, I use a `List view` component to display these reviews. To set the number of rows in the list view, I use the following expression: `{{pending_reviews.data.length}}`.

Then, I can put in the `List view` the compoents that will be used to display each row. In this case, it is an `Avatar` component and a `Text` component. In a row, we can use the i variable to access data of the current row. For example, to display the comment of the review in the Text component, I use the following expression: `{{pending_reviews.data[i].comment}}`.

To display the avatar, it is a little bit more complex because it is a relationship between reviews and customers. The `pending_reviews` query does not directly contain the customer's avatar. To get the customer's avatar, I need to create a new query that retrieves all customers with the ID of the review. I name this query `customers` and use the `customers` endpoint. I can now use the `customers` query to get the avatar of the customer who write the review in the `Avatar` component using the following expression: `{{customers.data.find((customer) => customer.id === pending_reviews.data[i].customer_id).avatar}}`.

The list of pending reviews is now ready!

![list of pending reviews](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iz55wvyet363pjps9gyz.jpeg)

The only problem is that it calls the API once for the reviews, and once for each review to fetch the author...

#Displaying a chart

One key benefit of using no-code tools is their ability to effortlessly create complex elements such as charts, which can be challenging to accomplish with traditional coding methods. Let's try this on the chart displaying the revenue from the last 30 days.

![chart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e81g5gw83ws31q4q0p99.jpg)

All I need to do is create the query `invoices_for_last_30_days` and use the chart component. With the sidebar, I can then select the `invoices_for_last_30_days` query as the data source, choose the `Line chart` type, and select to display only the `total` data from the query.

I have a problem when my query returns several invoices for the same day. To group invoices by day, I can directly transform the result of the query with some custom JavaScript code. For this particular case, I can accomplish this task with a `reduce` function.

![Code for chart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpllmav8fkkjx4fnwdfw.jpeg)

The chart is now ready!

![chart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hmw3e1z3qaobqan72095.jpeg)

Except I had to use JavaScript... Can a non-developer do that?

#Building a Multi-Page App

Creating a dashboard is nice but I need to have other views in my admin app. The react-admin demo is a complete app showing orders, invoices, products, customers, reviews, etc.

![Multi-Page App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p997tipnxwwh0cn4t07q.jpg)

Unfortunately, Retool does not allow to create multiple pages in a single app. To solve this problem, I have to create a new app.

Let's create a new app for the invoices list, that I name "Invoices list". Then, I add a header to my app with the left sidebar. By default, the header contains a `Navigation` component. This is exactly what I need! With the right sidebar, I can easily configure each link of the navigation. For example, I can set the link to the dashboard app and the label to "Dashboard".

![Dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/znzme33zzi6ckdmxh13t.jpeg)

This navigation has to be added in each separate app of my "multi-page" app. So, I also add it to the Dashboard app. Now, I can navigate between the two apps.

TIP:

If some components have to be shared between several apps, it is probably better to use the Module features provided by Retool. The queries can also be shared by exporting them to the "Query library".

#Creating A Table View

To create the invoices view, I first create a new query called `invoices` to retrieve all invoices, and use it in a `Table` component. Using the right sidebar, I can easily customize the column labels and select the fields to display in the table, such as hiding the `tax_rate`. The `Table` component also enables user to choose the sort field and add filters.

Currently, the order ID is visible in the table. To enhance the user experience, it would be great to directly display the order reference, similar to how the React Admin ReferenceField works. To achieve this, I have to create another query, `orders` to retrieve all orders. I can then add an "Order" column to the table and use JavaScript with the keyword `currentRow` to obtain the reference of the corresponding order ID:

![code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sg9xd3n2xmzp8nrzmmxj.png)

I would like to achieve a similar outcome with the customer ID by directly displaying the customer's avatar in the table. Unfortunately, it appears that it is not possible to nest a component like the `Avatar` component within the `Table` component. However, it is possible to use `Image URL` as the column type. To display the avatar, I can use the following expression:

![code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4p1sidkrlwlutqi92z2.png)

Additionally, I can create another column to display the customer's name by using the following expression:

![code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pyupotuyps3qx3a90kgv.png)

The invoices table is now ready!

![Invoices table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gog4fn5aex42m6g7ycym.jpeg)

But again, without basic coding knowledge, I would be very limited in terms of customization.

#Adding Actions To A Table

In the invoices list, I would like to have actions to edit or delete an invoice. To do this, I can use the `Actions` feature of the `Table` component. With the right sidebar, I can add a new action which I name `Delete` and select a query to run for this action. In this case, I create the `remove_invoice` query. In the query endpoint, I can access to the table data, so my endpoint is invoices/`{{ table1.data[i].id }}`.

As this action is deleting an invoice, I want to refresh the table once the action is executed. I can achieve this by using the "Event handlers" of the query. I set it to trigger the `invoices` query upon the successful execution of the `remove_invoice` query.

![Event handlers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kjller6ytjshaanifp98.jpeg)

Success! But is the notion of event handlers and triggers really a "no-code" notion?

#Conclusion

With the creation of a dashboard and a table view that includes a delete feature, my small admin application is now complete. It is only a subset of the react-admin e-commerce demo, but the main building blocks are there.

The main building blocks, but not the creation and edition features! That's maybe for another post.

In my opinion, as a JavaScript developer, this no-code tool has left me with mixed feelings. While it may be well-suited for building simple applications, more complex or customized projects will require the use of JS code. At the start of my experiment, I did not anticipate the need to write Javascript for nearly every component I had in mind.

In terms of development speed, I do not find it to be faster than using a framework such as React-Admin. This may be due to my background as a developer and my first-time use of the tool. For example, with React-Admin, the same type of table view can be created with just 3 lines of code.

Even for non-developers, I believe that it may not be enough user-friendly, as it requires a basic understanding of Javascript and how APIs work. For instance, creating a query requires knowledge of how to write a query endpoint, which may not be obvious for those without a development background.

To conclude, I think it requires the knowledge of a developer to tweak no-code tools such as ReTool enough to build moderately complex apps. And developers are more productive with low-code tools... So I wouldn't recommend it, except for simple dashboards.

Did you like this article? Share it!

✍️ Written by our team member Thibault Barrat :)