0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React×Go言語×MySQL(MariaDB)でToDoアプリを作る

Last updated at Posted at 2025-10-21

今回は、MySQL(MariaDB)を使ってReactGo言語を連携させてTodoアプリを作る方法を作ってみました。

アプリ作成の方針

MySQL・Go(バックエンド)・React(フロントエンド)を連携させたTodoアプリの構成は、モダンなフルスタック構成の代表例です。
ここでは、全体像 → 構成 → 実装手順 → コード例 の順で分かりやすく解説します。

🧩 全体構成イメージ

[React] ←→ [Go REST API] ←→ [MySQL Database]

React:ユーザーがTodoを追加・削除・完了チェックできるUI

Go:APIサーバー(JSON形式でデータ送受信)

MySQL:Todoデータを永続化

⚙️ 環境構成例

コンポーネント   使用する技術 
フロントエンド React (Vite or CRA)
バックエンド Go (net/http + gorilla/mux or Gin)
データベース MySQL
ORM (任意) GORM(GoのORM)
通信形式 REST API(JSON)

🪜 手順概要

① MySQLセットアップ

createTable.sql
CREATE DATABASE todo_app;
USE todo_app;

CREATE TABLE todos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    completed BOOLEAN DEFAULT FALSE
);

② Go(バックエンド)側の構築

下記のように、コマンドを入力してパッケージをインストールします。

cd backend
go mod init backend
go get gorm.io/driver/mysql
go get github.com/gorilla/mux
go get github.com/rs/cors
go mod tidy

Go言語のWebサーバ起動は下記のコマンドを実行

go run main.go
ディレクトリ構成例
backend/
 ├── main.go
 ├── go.mod
 ├── handlers/
 │    └── todo.go
 ├── models/
 │    └── todo.go
 └── db/
      └── db.go
1. GORMを使ってDB接続

go get gorm.io/gorm gorm.io/driver/mysql github.com/gorilla/mux cors
db/db.go

db/db.go
package db

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func Connect() {
	dsn := "root:password@tcp(127.0.0.1:3306)/todo_app?charset=utf8mb4&parseTime=True&loc=Local"
	database, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("DB接続に失敗しました: " + err.Error())
	}
	DB = database
}

root:password@tcp(127.0.0.1:3306)/todo_app?charset=utf8mb4&parseTime=True&loc=Local について説明します。
この部分は MySQLに接続するための「DSN(Data Source Name)」 と呼ばれる設定文字列です。
Go(GORMやMySQLドライバ)が「どのサーバーの、どのデータベースに、どんな設定で接続するか」を指定しています。

🔹 ① root:password
ユーザー名とパスワード

root → MySQLのユーザー名(デフォルトの管理者ユーザー)

password → そのユーザーのパスワード

つまり「MySQLにログインするための認証情報」です。

#####🔹 ② @tcp(127.0.0.1:3306)

接続先(ホストとポート)

tcp → TCP接続を使う(MySQLは通常TCPで通信)

127.0.0.1 → ローカル(あなたのPC)を指すIPアドレス

3306 → MySQLの標準ポート番号

つまり「自分のパソコンのMySQLサーバーにTCPで接続する」という意味です。

🔹 ③ /todo_app
データベース名

ここで指定されたデータベースを使います。
この場合は todo_app という名前のデータベースです。

🔹 ④ ?charset=utf8mb4&parseTime=True&loc=Local
接続オプション(パラメータ)
 パラメータ  意味 
 charset=utf8mb4  MySQLで日本語や絵文字も扱える文字コード設定 
 parseTime=True  DATETIME/TIMESTAMP型を自動的にGoのtime.Time型として扱う 
 loc=Local  タイムゾーンをローカル(日本時間など)に設定 
2. モデル定義

models/todo.go

models/todo.go
package models

import "gorm.io/gorm"

type Todo struct {
	gorm.Model
	Title     string `json:"title"`
	Completed bool   `json:"completed"`
}
3. ハンドラー(APIエンドポイント)

handlers/todo.go

handlers/todo.go
package handlers

import (
	"encoding/json"
	"net/http"

	"github.com/gorilla/mux"
	"your_project/db"
	"your_project/models"
)

func GetTodos(w http.ResponseWriter, r *http.Request) {
	var todos []models.Todo
	db.DB.Find(&todos)
	json.NewEncoder(w).Encode(todos)
}

func CreateTodo(w http.ResponseWriter, r *http.Request) {
	var todo models.Todo
	json.NewDecoder(r.Body).Decode(&todo)
	db.DB.Create(&todo)
	json.NewEncoder(w).Encode(todo)
}

func ToggleTodo(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	var todo models.Todo
	db.DB.First(&todo, params["id"])
	todo.Completed = !todo.Completed
	db.DB.Save(&todo)
	json.NewEncoder(w).Encode(todo)
}

func DeleteTodo(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	db.DB.Delete(&models.Todo{}, params["id"])
	w.WriteHeader(http.StatusNoContent)
}
4. main.go にルーティング設定
main.go
package main

import (
	"log"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/rs/cors"

	"your_project/db"
	"your_project/handlers"
	"your_project/models"
)

func main() {
	db.Connect()
	db.DB.AutoMigrate(&models.Todo{})

	r := mux.NewRouter()
	r.HandleFunc("/todos", handlers.GetTodos).Methods("GET")
	r.HandleFunc("/todos", handlers.CreateTodo).Methods("POST")
	r.HandleFunc("/todos/{id}", handlers.ToggleTodo).Methods("PUT")
	r.HandleFunc("/todos/{id}", handlers.DeleteTodo).Methods("DELETE")

	handler := cors.AllowAll().Handler(r)
	log.Println("Server running on :8080")
	log.Fatal(http.ListenAndServe(":8080", handler))
}

③ React(フロントエンド)側

npm create vite@latest frontend -- --template react
cd frontend
npm install axios
npm run dev

src/App.jsx

src/App.jsx
import { useEffect, useState } from "react";
import axios from "axios";

const API_URL = "http://localhost:8080/todos";

export default function App() {
  const [todos, setTodos] = useState([]);
  const [title, setTitle] = useState("");

  useEffect(() => {
    axios.get(API_URL).then((res) => setTodos(res.data));
  }, []);

  const addTodo = async () => {
    const res = await axios.post(API_URL, { title });
    setTodos([...todos, res.data]);
    setTitle("");
  };

  const toggleTodo = async (id) => {
    const res = await axios.put(`${API_URL}/${id}`);
    setTodos(todos.map((t) => (t.id === id ? res.data : t)));
  };

  const deleteTodo = async (id) => {
    await axios.delete(`${API_URL}/${id}`);
    setTodos(todos.filter((t) => t.id !== id));
  };

  return (
    <div style={{ maxWidth: 400, margin: "auto" }}>
      <h1>Todo List</h1>
      <input value={title} onChange={(e) => setTitle(e.target.value)} />
      <button onClick={addTodo}>追加</button>

      <ul>
        {todos.map((todo) => (
          <li key={todo.ID}>
            <span
              onClick={() => toggleTodo(todo.ID)}
              style={{
                textDecoration: todo.completed ? "line-through" : "none",
                cursor: "pointer",
              }}
            >
              {todo.title}
            </span>
            <button onClick={() => deleteTodo(todo.ID)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

🚀 実行手順まとめ

MySQL起動 → CREATE DATABASE todo_app;

Goサーバー起動 → go run main.go

React起動 → npm run dev

ブラウザで http://localhost:5173
にアクセス
→ Todoアプリ完成🎉

Go言語関連

サイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?