Learn Ruby on Rails Book

Displaying list of tasks

In the previous chapters we saw how we can integrate backend and frontend. Let's make use of those concepts to introduce a new feature where we will fetch the list of all tasks from backend to display it in our frontend.

Features

These are the basic requirements of this feature:

  • A dashboard which is also the home page of our application.

  • An unordered list of all tasks which will be displayed on the application home page.

displaying list of tasks feature

Technical design

To implement this feature we need to introduce the following changes:

On the backend

  • Add an index action in the TasksController which will respond with a JSON of all tasks.

On the frontend

  • Add an API for fetching the list of tasks from the backend.

  • Add a TaskList component which will use the reusable Table component we created to display the tasks.

  • Add a Dashboard component which will act as a home page for the application. Dashboard component will call the API to fetch task list and pass this list as a prop to the TaskList component which will pass it down further to the Table component.

  • Add a route in the App component to render the Dashboard.

Preparing to display list of tasks

First, let's create a file that contains the APIs for listing tasks. To do so, run the following command:

1touch app/javascript/src/apis/tasks.js

In tasks.js, paste the following content.

1import axios from "axios";
2
3const list = () => axios.get("/tasks");
4
5const tasksApi = {
6  list,
7};
8
9export default tasksApi;

Now let's create a ListTasks component. This component will be the parent component which displays the list of tasks. We can make use of our reusable components like Table over here. Run the following command:

1touch app/javascript/src/components/Tasks/ListTasks.jsx

In ListTasks.jsx paste the following content:

1import React from "react";
2import Table from "./Table";
3
4const ListTasks = ({ data }) => {
5  return <Table data={data} />;
6};
7
8export default ListTasks;

Displaying list of tasks

Now let's try to display list of tasks from the database. We have created a component ListTasks which will render the table containing the tasks.

Now let's create a Dashboard component which will render the ListTasks component. To do so, run the following command:

1mkdir -p app/javascript/src/components/Dashboard/
2touch app/javascript/src/components/Dashboard/index.jsx

We recommend using Ramdajs library over lodash for most of the JavaScript operations since it's a well maintained, functional and lightweight.

In general when checking whether a variable is null/empty etc, use isNil/isEmpty from ramda.

Install ramda first:

1yarn add ramda

Inside index.jsx, paste the following contents

1import React, { useState, useEffect } from "react";
2import { isNil, isEmpty, either } from "ramda";
3
4import Container from "components/Container";
5import ListTasks from "components/Tasks/ListTasks";
6import PageLoader from "components/PageLoader";
7import tasksApi from "apis/tasks";
8
9const Dashboard = ({ history }) => {
10  const [tasks, setTasks] = useState([]);
11  const [loading, setLoading] = useState(true);
12
13  const fetchTasks = async () => {
14    try {
15      const response = await tasksApi.list();
16      setTasks(response.data.tasks);
17      setLoading(false);
18    } catch (error) {
19      logger.error(error);
20      setLoading(false);
21    }
22  };
23
24  useEffect(() => {
25    fetchTasks();
26  }, []);
27
28  if (loading) {
29    return (
30      <div className="w-screen h-screen">
31        <PageLoader />
32      </div>
33    );
34  }
35
36  if (!either(isNil, isEmpty)(tasks)) {
37    return (
38      <Container>
39        <ListTasks data={tasks} />
40      </Container>
41    );
42  }
43
44  return (
45    <Container>
46      <h1 className="text-xl leading-5 text-center">
47        You have no tasks assigned 😔
48      </h1>
49    </Container>
50  );
51};
52
53export default Dashboard;

Now, we have created a Dashboard and a ListTasks component that is rendered inside the dashboard.

Finally, let's create a React route to render our Dashboard component.

To do so, add the following lines to App.jsx:

1// previous imports
2import Dashboard from "components/Dashboard";
3
4const App = () => {
5  // previous code without any changes
6  return (
7    <Router>
8      <Switch>
9        // <--- rest of the code if any ----->
10        <Route exact path="/dashboard" component={Dashboard} />
11      </Switch>
12    </Router>
13  );
14};
15
16export default App;

Update the index action of TasksController, to send JSON response with tasks:

1def index
2  tasks = Task.all
3  render status: :ok, json: { tasks: tasks }
4end

Now visit URL http://localhost:3000/dashboard so that you can see all the tasks in the browser.

1git add -A
2git commit -m "Added ability to display list of tasks"
⌘K
    to navigateEnterto select Escto close
    Previous
    Next