基本の復習も兼ねてTodoリストを作りました。
Reactでは、非同期でHTTP通信を行うためにaxiosを使っています。
Goでは、GORMとechoを使っています。
##React
Todo.js
import React from 'react';
import InputField from './InputField';
import List from './List';
import http from './http';
class Todo extends React.Component {
constructor() {
super();
this.state = {
text: "",
lists: [],
}
}
componentDidMount() {
this.getTodoList();
}
getTodoList = () => {
return http
.get('/todo')
.then((response) => {
this.setState({ lists: response.data })
})
.catch(error => {
console.log(error)
})
}
handleChange = e => {
this.setState({ text: e.target.value })
}
handleSubmit = () => {
if (this.state.text === "") {
return window.alert("入力してください")
}
return http
.post('/todo', {
text: this.state.text
})
.then(() => {
this.setState({ text: "" });
this.getTodoList();
}
)
.catch(error => {
console.log(error)
})
}
handleDelete = (list) => {
return http
.delete(`/todo/${list.id}`)
.then(() =>
this.getTodoList()
)
.catch(error => {
console.log(error)
})
}
render() {
return (
<div className="todo">
<div className="todo-title">
<h1>Todo</h1>
</div>
<InputField
text={this.state.text}
handleChange={this.handleChange}
handleSubmit={this.handleSubmit}
/>
<List
lists={this.state.lists}
handleDelete={this.handleDelete}
/>
</div>
)
}
}
export default Todo;
InputField.js
import React from 'react';
export default function InputField(props) {
return (
<div className="todo-input-field">
<input placeholder="入力しよう" value={props.text} onChange={e => props.handleChange(e)}></input>
<button onClick={props.handleSubmit}>保存</button>
</div>
)
}
http.js
import axios from 'axios';
const API_HOST = process.env.REACT_APP_API_HOST || 'http://localhost:〇〇〇〇';
const http = axios.create({
baseURL: API_HOST,
});
export default http;
##Go
main.go
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"パスに合わせて他のパッケージをimport"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
const defaultPort = "〇〇〇〇"
func port() string {
p := os.Getenv("PORT")
if p != "" {
return ":" + p
}
return ":" + defaultPort
}
func main() {
connStr := fmt.Sprintf(
"%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True",
"DBUSER",
"DBPASSWORD",
"DBPROTOCOL",
"DBNAME",
)
db, err := gorm.Open("mysql", connStr)
if err != nil {
log.Fatal(err)
}
h := handler.New(db)
server := &http.Server{
Addr: port(),
Handler: h,
}
go func() {
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
<-stop
log.Println("Shutting down...")
if err := server.Shutdown(context.Background()); err != nil {
log.Println("Unable to shutdown:", err)
}
log.Println("Server stopped")
}()
log.Println("Listening on http://localhost" + port())
if err := server.ListenAndServe(); err != http.ErrServerClosed {
log.Fatal(err)
}
}
handler.go
package handler
import (
"net/http"
"github.com/jinzhu/gorm"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
func New(db *gorm.DB) http.Handler {
e := echo.New()
e.Use(middleware.CORS())
h := &handler{
DB: db,
}
e.GET("/health", h.health)
e.GET("/todo", h.getTodoLists)
e.POST("/todo", h.createTodo)
e.DELETE("/todo/:id", h.deleteTodo)
return e
}
type handler struct {
DB *gorm.DB
}
func (h *handler) health(c echo.Context) error {
return c.JSON(http.StatusOK, map[string]string{"message": "OK"})
}
list.go
package handler
import (
"net/http"
"time"
"github.com/labstack/echo"
)
type List struct {
ID uint `json:"id"`
Text string `json:"text"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
func (h *handler) getTodoLists(c echo.Context) error {
var lists []List
err := h.DB.Find(&lists).Error
if err != nil {
return err
}
return c.JSON(http.StatusOK, lists)
}
func (h *handler) createTodo(c echo.Context) error {
var list List
err := c.Bind(&list)
if err != nil {
return err
}
err = h.DB.Create(&list).Error
if err != nil {
return err
}
return c.JSON(http.StatusOK, list)
}
func (h *handler) deleteTodo(c echo.Context) error {
var list List
paramID := c.Param("id")
err := h.DB.Where("id=?", paramID).Delete(&list).Error
if err != nil {
return err
}
return c.JSON(http.StatusOK, list)
}
本来であれば、type ~ struct 構造体を他のパッケージからインポートするのがベストな気がするのですが、importがうまくできなかったので、list.goにまとめて書きました。
この問題は解決したい、、、
##DB
todoというデータベースの中にlistsテーブルがあり、中身は画像のようになってます。
このような形で簡単なTodoリストが作成できると思います。