Back to articles

Building a Full-Stack CRUD App with React, TypeScript, and a Serverless API

AuthorMajd Muhtaseb06/24/202515 minutes
Building a Full-Stack CRUD App with React, TypeScript, and a Serverless API

Introduction

This article will guide you through building a basic CRUD (Create, Read, Update, Delete) application using a modern stack: React with TypeScript for the frontend and a serverless API (using, for example, AWS Lambda and API Gateway, or Netlify Functions) for the backend. This stack offers scalability, maintainability, and a great developer experience. We'll focus on the core concepts and provide examples to get you started.

Frontend (React with TypeScript)

Setting up the project

First, create a new React project with TypeScript:

npx create-react-app my-crud-app --template typescript
cd my-crud-app

Defining the Data Type

Let's define a simple Task type:

// src/Task.ts
export interface Task {
  id: string;
  title: string;
  description: string;
  completed: boolean;
}

Creating the Task List Component

// src/components/TaskList.tsx
import React, { useState, useEffect } from 'react';
import { Task } from '../Task';

const TaskList: React.FC = () => {
  const [tasks, setTasks] = useState<Task[]>([]);

  useEffect(() => {
    // Fetch tasks from the API on component mount
    fetchTasks();
  }, []);

  const fetchTasks = async () => {
    try {
      const response = await fetch('/.netlify/functions/get-tasks'); // Assuming Netlify Functions
      const data = await response.json();
      setTasks(data);
    } catch (error) {
      console.error("Error fetching tasks:", error);
    }
  };

  const handleComplete = async (id: string) => {
        try {
            await fetch(`/.netlify/functions/update-task/${id}`, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ completed: !tasks.find(task => task.id === id)?.completed }),
            });
            fetchTasks();
        } catch (error) {
            console.error("Error updating task:", error);
        }

  }

  return (
    <ul>
      {tasks.map((task) => (
        <li key={task.id}>
          {task.title} - {task.description} - Completed: {task.completed ? 'Yes' : 'No'}
          <button onClick={() => handleComplete(task.id)}>Toggle Complete</button>
        </li>
      ))}
    </ul>
  );
};

export default TaskList;

Backend (Serverless API - Example: Netlify Functions)

Setting up Netlify Functions

Create a netlify.toml file in your project root:

[build]
  functions = "netlify/functions"

Creating the Get Tasks Function

// netlify/functions/get-tasks.js
exports.handler = async (event, context) => {
  // In a real application, you would fetch from a database
  const tasks = [
    { id: "1", title: "Learn React", description: "Master React fundamentals", completed: false },
    { id: "2", title: "Build API", description: "Create a serverless API", completed: true },
  ];

  return {
    statusCode: 200,
    body: JSON.stringify(tasks),
    headers: {
      "Content-Type": "application/json",
    },
  };
};

Creating the Update Task Function

// netlify/functions/update-task/[id].js

exports.handler = async (event, context) => {
    const taskId = event.pathParameters.id;
    const { completed } = JSON.parse(event.body);

    // In a real application, you would update the task in a database
    // For this example, we'll just log the ID and completion status
    console.log(`Updating task with ID: ${taskId} to completed: ${completed}`);

    return {
        statusCode: 200,
        body: JSON.stringify({ message: `Task ${taskId} updated to completed: ${completed}` }),
        headers: {
            "Content-Type": "application/json",
        },
    };
};

Conclusion

This is a simplified example, but it illustrates the core principles of building a full-stack CRUD application with React, TypeScript, and a serverless API. Remember to replace the mock data with a real database connection for a production-ready application.