DEV Community

react-admin for React-admin

Posted on • Originally published at marmelab.com on

Are No-Code Tools A Good Choice For Developers?

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

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

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

Code

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

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

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

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

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

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

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

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

The chart is now ready!

chart

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

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

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

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

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

code

The invoices table is now ready!

Invoices table

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

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 :)

Top comments (0)