Berikut adalah proyek sederhana yang terdiri dari frontend (React.js) dan backend (Go dengan Fiber) untuk aplikasi todo-list yang bisa melakukan operasi read, create, dan delete dengan PostgreSQL sebagai basis datanya.
Struktur Folder
Copy todo-frontend/
├── public
│ └── index.html
├── src
│ ├── App.js
│ ├── index.js
│ ├── components
│ │ └── ProductList.js
├── package.json
└── .env
todo-backend/
├── main.go
├── go.mod
├── go.sum
└── database
└── connection.go
todo-frontend
1. File: todo-frontend/public/index.html
Copy <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo List</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
2. File: todo-frontend/src/index.js
Copy import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
3. File: todo-frontend/src/App.js
Copy import React from 'react';
import ProductList from './components/ProductList';
function App() {
return (
<div className="App">
<ProductList />
</div>
);
}
export default App;
4. File: todo-frontend/src/components/ProductList.js
Copy import React, { useState, useEffect } from 'react';
import axios from 'axios';
const ProductList = () => {
const [products, setProducts] = useState([]);
const [name, setName] = useState('');
const [price, setPrice] = useState('');
const [stock, setStock] = useState('');
useEffect(() => {
fetchProducts();
}, []);
const fetchProducts = async () => {
const response = await axios.get(`${process.env.REACT_APP_API_URL}/products`);
setProducts(response.data);
};
const createProduct = async () => {
const newProduct = { name, price: parseFloat(price), stock: parseInt(stock) };
await axios.post(`${process.env.REACT_APP_API_URL}/products`, newProduct);
fetchProducts();
setName('');
setPrice('');
setStock('');
};
const deleteProduct = async (id) => {
await axios.delete(`${process.env.REACT_APP_API_URL}/products/${id}`);
fetchProducts();
};
return (
<div>
<h1>Product List</h1>
<ul>
{products.map(product => (
<li key={product.id}>
{product.name} - ${product.price} - Stock: {product.stock}
<button onClick={() => deleteProduct(product.id)}>Delete</button>
</li>
))}
</ul>
<div>
<h2>Create Product</h2>
<input
type="text"
placeholder="Name"
value={name}
onChange={e => setName(e.target.value)}
/>
<input
type="text"
placeholder="Price"
value={price}
onChange={e => setPrice(e.target.value)}
/>
<input
type="text"
placeholder="Stock"
value={stock}
onChange={e => setStock(e.target.value)}
/>
<button onClick={createProduct}>Create</button>
</div>
</div>
);
};
export default ProductList;
5. File: todo-frontend/package.json
Copy {
"name": "todo-frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.7.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
6. File: todo-frontend/.env
Copy REACT_APP_API_URL=http://localhost:3000
todo-backend
1. File: todo-backend/main.go
Copy package main
import (
"todo-backend/database"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"gorm.io/gorm"
)
type Product struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name"`
Price float64 `json:"price"`
Stock int `json:"stock"`
}
var DB *gorm.DB
func main() {
database.Connect()
DB = database.DB
DB.AutoMigrate(&Product{})
app := fiber.New()
app.Use(cors.New(cors.Config{
AllowOrigins: "*",
AllowHeaders: "Origin, Content-Type, Accept",
}))
app.Get("/products", GetProducts)
app.Post("/products", CreateProduct)
app.Delete("/products/:id", DeleteProduct)
app.Listen(":3000")
}
func GetProducts(c *fiber.Ctx) error {
var products []Product
DB.Find(&products)
return c.JSON(products)
}
func CreateProduct(c *fiber.Ctx) error {
product := new(Product)
if err := c.BodyParser(product); err != nil {
return c.Status(400).SendString(err.Error())
}
DB.Create(&product)
return c.JSON(product)
}
func DeleteProduct(c *fiber.Ctx) error {
id := c.Params("id")
var product Product
DB.First(&product, id)
if product.ID == 0 {
return c.Status(404).SendString("No Product Found with ID")
}
DB.Delete(&product)
return c.SendString("Product Successfully deleted")
}
2. File: todo-backend/database/connection.go
Copy package database
import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var DB *gorm.DB
func Connect() {
var err error
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable",
os.Getenv("DB_HOST"),
os.Getenv("DB_USER"),
os.Getenv("DB_PASSWORD"),
os.Getenv("DB_DATABASE"),
os.Getenv("DB_PORT"),
)
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
log.Fatal("Failed to connect to database: ", err)
}
db, err := DB.DB()
if err != nil {
log.Fatal("Failed to get database connection: ", err)
}
db.SetMaxIdleConns(10)
db.SetMaxOpenConns(100)
db.SetConnMaxLifetime(time.Hour)
}
3. File: todo-backend/go.mod
Copy module todo-backend
go 1.18
require (
github.com/gofiber/fiber/v2 v2.52.4
gorm.io/driver/postgres v1.5.7
gorm.io/gorm v1.25.10
)
4. File: todo-backend/go.sum
(Secara otomatis dibuat oleh Go saat Anda menjalankan go mod tidy
atau menambahkan dependensi.)
Menjalankan Proyek
Backend
Pastikan PostgreSQL Berjalan :
Pastikan PostgreSQL berjalan dan dapat diakses dengan kredensial yang diberikan.
Anda bisa menggunakan Docker untuk menjalankan PostgreSQL:
Copy docker run --name postgres-db -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=root -e POSTGRES_DB=marketplace -p 5432:5432 -d postgres
Set Environment Variables :
Buat file .env
di root folder todo-backend
dan isi dengan:
Copy DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=root
DB_DATABASE=marketplace
end`, jalankan: sh go mod tidy go run main.go
Frontend
Install Dependencies :
Di folder todo-frontend
, jalankan:
Jalankan Frontend :
Masih di folder todo-frontend
, jalankan:
Frontend akan berjalan di http://localhost:3000
dan akan berkomunikasi dengan backend yang juga berjalan di port 3000.
Dengan mengikuti langkah-langkah di atas, Anda akan memiliki aplikasi todo-list sederhana yang dapat melakukan operasi read, create, dan delete menggunakan React untuk frontend dan Go dengan Fiber untuk backend.
Last updated 10 months ago