Building a To-Do App with RTK Query
Published: 2024-05-19 10:08:07

In this guide, we'll walk you through creating a simple To-Do application using RTK Query, a powerful data fetching and caching tool from Redux Toolkit. We'll use an open-source API to manage our to-dos. By the end of this guide, you'll have a fully functional To-Do app and a solid understanding of how to integrate RTK Query in your projects.

**Prerequisites**

Before we start, make sure you have the following installed:

- Node.js
- npm or yarn
- A code editor (e.g., VSCode)

> Step 1: Setting Up the Project

**1. Initialize a new React project:**

```
npx create-react-app rtk-query-todo
cd rtk-query-todo
```

**2. Install necessary dependencies:**

```
npm install @reduxjs/toolkit react-redux
```


> Step 2: Setting Up RTK Query

**1. Create an API slice:**
     First, let's create an API slice to manage our To-Do operations. We'll use the [JSONPlaceholder API](https://jsonplaceholder.typicode.com/) for demonstration purposes.

Create a file named **apiSlice.js** in the **<u>src</u>** directory:

```
// src/apiSlice.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const apiSlice = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({ baseUrl: 'https://jsonplaceholder.typicode.com/' }),
  endpoints: (builder) => ({
    getTodos: builder.query({
      query: () => 'todos',
    }),
    addTodo: builder.mutation({
      query: (newTodo) => ({
        url: 'todos',
        method: 'POST',
        body: newTodo,
      }),
    }),
    deleteTodo: builder.mutation({
      query: (id) => ({
        url: `todos/${id}`,
        method: 'DELETE',
      }),
    }),
  }),
});

export const { useGetTodosQuery, useAddTodoMutation, useDeleteTodoMutation } = apiSlice;
```

**2. Configure the store:**

Next, let's configure our Redux store to include the API slice.

```
// src/app/store.js
import { configureStore } from '@reduxjs/toolkit';
import { apiSlice } from '../apiSlice';

export const store = configureStore({
  reducer: {
    [apiSlice.reducerPath]: apiSlice.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(apiSlice.middleware),
});
```

**3. Provide the store to your app:**

Wrap your application with the Redux provider in **index.js**.

```
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';
import './index.css';

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
```

> Step 3: Creating the To-Do Components

**1. Create a To-Do List component:**

```
// src/components/TodoList.js
import React from 'react';
import { useGetTodosQuery, useDeleteTodoMutation } from '../apiSlice';

const TodoList = () => {
  const { data: todos, error, isLoading } = useGetTodosQuery();
  const [deleteTodo] = useDeleteTodoMutation();

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error loading todos</p>;

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>
          {todo.title}
          <button onClick={() => deleteTodo(todo.id)}>Delete</button>
        </li>
      ))}
    </ul>
  );
};

export default TodoList;
```

**2. Create an Add To-Do component:**

```
// src/components/AddTodo.js
import React, { useState } from 'react';
import { useAddTodoMutation } from '../apiSlice';

const AddTodo = () => {
  const [title, setTitle] = useState('');
  const [addTodo] = useAddTodoMutation();

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (title) {
      await addTodo({
        title,
        completed: false,
      });
      setTitle('');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        placeholder="Add a new todo"
      />
      <button type="submit">Add Todo</button>
    </form>
  );
};

export default AddTodo;
```

**3. Combine components in the main App:**
```
// src/App.js
import React from 'react';
import TodoList from './components/TodoList';
import AddTodo from './components/AddTodo';

function App() {
  return (
    <div className="App">
      <h1>RTK Query To-Do App</h1>
      <AddTodo />
      <TodoList />
    </div>
  );
}

export default App;
```

> Step 4: Running the Application

Now, you can run your application using the following command:

```
npm start
```

Your application should be up and running at http://localhost:3000. You can add new to-dos and delete existing ones using the JSONPlaceholder API.


> Conclusion

In this guide, we covered how to create a simple To-Do application using RTK Query with an open-source API. We set up our Redux store, created API slices, and built components for listing and adding to-dos. RTK Query simplifies data fetching and caching, making it easier to manage server-side data in your applications.

Feel free to expand on this project by adding more features such as editing to-dos, marking them as completed, or integrating user authentication. Happy coding!