🍱
Remix + Laravel 8 のCRUD作成
概要:
Remixと、Laravel 8 API の組合せでCRUD作成の例になります。
-
前の, next.js + Laravelと似ています。
-
Laravel APIは、前のNext.js版と同じです
-
Remix追加時に、vercel を選択しました
構成
- remix : 1.0.6
- Laravel 8
- mysql
参考のコード
- laravel は、下記
参考のぺージ
- Remix , Laravel の通信も、前のnext.js版と同様
-
準備
-
axios.ts : /app/lib/axios.ts
前と同様、カスタム版 axiosを読込ます
axios.ts
import Axios from 'axios'
import Config from '../../config';
//console.log(Config.API_URL);
const axios = Axios.create({
baseURL: Config.API_URL,
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
withCredentials: true,
})
export default axios
- config.ts, API_URL 設定
config.ts
const config = {
// ...
API_URL: 'http://localhost:8000',
}
export default config;
CRUDの作成
- index.ts : /app/routes/tasks/index.tsx
index.ts
//import { useEffect, useRef } from "react";
import React, {useState, useEffect, useRef} from 'react';
import type { MetaFunction, LoaderFunction } from "remix";
import { useLoaderData, Link } from "remix";
import { Form, json, useActionData, redirect } from "remix";
import Config from '../../../config'
import LibCookie from '../../lib/LibCookie'
import LibFlash from '../../lib/LibFlash';
import axios from '~/lib/axios';
export let meta: MetaFunction = () => {
return {
title: "Tasks",
description: "Welcome to remix!"
};
};
export let loader: LoaderFunction = async () => {
return json([]);
}
export default function Page() {
// state
const [data, setData] = useState([]);
const [message, setMessage] = useState("");
const initTask = async function(){
const res = await axios.get('/api/tasks/list');
console.log(res.data);
setData(res.data);
}
const keyUid = Config.COOKIE_KEY_USER_ID;
useEffect(() => {
const uid = LibCookie.get_cookie(keyUid);
console.log("uid=", uid);
if(uid === null){
// console.log("uid nothing");
// location.href = '/login';
}
const msg: any = LibFlash.getMessageObject();
setMessage(msg.success);
console.log(msg);
initTask();
},[])
//console.log(data);
return (
<div className="remix__page">
{ message ?
<div className="alert alert-success" role="alert">{message}</div>
: <div />
}
<main>
<h3>Tasks - Index</h3>
<hr />
<Link to="/tasks/create" className="btn btn-primary">Create</Link>
<hr />
<ul>
{data.map(item => (
<li key={item.id} className="remix__page__resource">
<h3>{item.title}</h3>
<Link to={`${item.id}`} className="btn btn-sm btn-outline-primary mx-2">Show</Link>
<Link to={`edit/${item.id}`}
className="btn btn-sm btn-outline-primary">edit
</Link>
<hr className="my-2" />
</li>
))}
</ul>
</main>
</div>
);
}
- create.ts: /app/routes/tasks/create.tsx
create.tsx
import { useEffect, useRef } from "react";
import type { MetaFunction, LoaderFunction } from "remix";
import { Form, json, useActionData, redirect } from "remix";
import LibFlash from '../../lib/LibFlash'
import axios from '~/lib/axios';
export let meta: MetaFunction = () => {
return {
title: "Task Create",
description: "Welcome to remix!"
};
};
export default function Page() {
//console.log(cfg.OK_CODE);
let onClick = async function(){
console.log("#onClick");
const title = document.querySelector<HTMLInputElement>('#title');
const item = {
title: title.value,
content: "",
}
const res = await axios.post(
'/api/tasks/create', item
);
console.log(res);
LibFlash.setMessage("OK, Save");
alert("OK, Save");
location.href = "/tasks";
}
return (
<div className="remix__page">
<main>
<h2>Task - Create</h2>
<hr />
<label>
<div>Title:</div>
<input type="text" className="form-control" name="title" id="title" />
</label>
<hr />
<button onClick={() => onClick()} className="btn btn-primary">Save
</button>
{/*
*/}
</main>
</div>
);
}
-
show
/app/routes/tasks/$id.tsx -
edit
/app/routes/tasks/edit/$id.tsx
....
Discussion