🍱

Remix + Laravel 8 のCRUD作成

2021/12/10に公開

概要:

Remixと、Laravel 8 API の組合せでCRUD作成の例になります。

  • 前の, next.js + Laravelと似ています。

  • Laravel APIは、前のNext.js版と同じです

  • Remix追加時に、vercel を選択しました


構成

  • remix : 1.0.6
  • Laravel 8
  • mysql

参考のコード

https://github.com/kuc-arc-f/remix22

  • laravel は、下記

https://github.com/kuc-arc-f/lara8d


参考のぺージ

https://zenn.dev/knaka0209/articles/f0082eb105b2c4

  • 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