この記事の前に
この記事はpart2です、part1は下記リンクになります。
この記事で行うこと
- React(フロント) + CodeIgniter4(バックエンド)を利用
- CodeIgniter4のインストール・設定から、Reactのインストール・設定、最終的にフロント側からバックエンド側へデータの送受信ができている状態までの環境を構築する
その他の環境
- macOS Monterey(macbook air 2020 ,M1チップ)
- VisualStudio Code
参考にしたサイト記事
英語の記事ですが書いてくださった方に感謝
構築スタート
フロントエンド(React)
Reactプロジェクト作成
必要ですので、インストールの有無を確認してください。
node -v
npm -v
確認ができたら、 myProject ディレクトリに移動します。
その後下記コマンドを実行。
npx create-react-app frontend
frontend フォルダが作成され、合わせてアプリケーションが内包されます。
続いて、
npm install react-router-dom axios bulma
インストールが完了した後、
npm start
問題なければ、http://localhost:3000 にて画面の表示がされます。
コンポーネントを作成する
frontend/srcフォルダ内に、componentsフォルダを作成し、ProductList.js、AddProduct.js、EditProduct.js、のファイルを作成します。
ProductList.js
下記の通りに記載します。
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import { Link } from 'react-router-dom'
const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(() => {
getProducts();
},[]);
const getProducts = async () => {
const products = await axios.get('http://localhost:8080/products');
setProducts(products.data);
}
const deleteProduct = async (id) =>{
await axios.delete(`http://localhost:8080/products/${id}`);
getProducts();
}
return (
<div>
<Link to="/add" className="button is-primary mt-5">Add New</Link>
<table className="table is-striped is-fullwidth">
<thead>
<tr>
<th>No</th>
<th>Title</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{ products.map((product, index) => (
<tr key={product.id}>
<td>{index + 1}</td>
<td>{product.title}</td>
<td>{product.price}</td>
<td>
<Link to={`/edit/${product.id}`} className="button is-small is-info">Edit</Link>
<button onClick={() => deleteProduct(product.id)} className="button is-small is-danger">Delete</button>
</td>
</tr>
)) }
</tbody>
</table>
</div>
)
}
export default ProductList
AddProduct.js
下記の通りにします。
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import axios from 'axios'
const AddProduct = () => {
const [title, setTitle] = useState('')
const [price, setPrice] = useState(0)
const navigate = useNavigate()
const saveProduct = async (e) => {
e.preventDefault();
await axios.post('http://localhost:8080/products', {
title: title,
price: price
})
navigate("/")
}
return (
<div>
<form onSubmit={ saveProduct }>
<div className="field">
<label className="label">Name</label>
<input type="text" className="input" value={ title } onChange={ (e) => setTitle(e.target.value) } placeholder="nama" />
</div>
<div className="field">
<label className="label">Price</label>
<input type="text" className="input" value={ price } onChange={ (e) => setPrice(e.target.value) } placeholder="harga" />
</div>
<div className="field">
<button className="button is-primary">Save</button>
<button className="button is-warning" onClick={() => navigate("/")}>Cancel</button>
</div>
</form>
</div>
)
};
export default AddProduct;
EditProduct.js
下記の通りにします。
import React, { useEffect, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import axios from 'axios'
const EditProduct = () => {
const [title, setTitle] = useState('')
const [price, setPrice] = useState(0)
const navigate = useNavigate()
const { id } = useParams()
const updateProduct = async (e) => {
e.preventDefault();
await axios.post(`http://localhost:8080/products/update/${id}`, {
title: title,
price: price
})
navigate("/")
}
useEffect(() => {
getProductById()
}, [])
const getProductById = async () => {
const response = await axios.get(`http://localhost:8080/products/${id}`);
setTitle(response.data.title)
setPrice(response.data.price)
}
return (
<div>
<form onSubmit={ updateProduct }>
<div className="field">
<label className="label">Nama Barang</label>
<input type="text" className="input" value={ title } onChange={ (e) => setTitle(e.target.value) } placeholder="nama" />
</div>
<div className="field">
<label className="label">Harga</label>
<input type="text" className="input" value={ price } onChange={ (e) => setPrice(e.target.value) } placeholder="harga" />
</div>
<div className="field">
<button className="button is-primary">Update</button>
<button className="button is-warning" onClick={() => navigate("/")}>Cancel</button>
</div>
</form>
</div>
)
};
export default EditProduct;
App.jsを変更する
frontend/srcフォルダ内の, App.js を開きます。
下記の通り変更します。
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import ProductList from './components/ProductList';
import AddProduct from './components/AddProduct';
import EditProduct from './components/EditProduct';
import './App.css';
function App() {
return (
<Router>
<div className="container">
<Routes>
<Route exact path="/" element={<ProductList />} />
<Route path="/add" element={<AddProduct />} />
<Route path="/edit/:id" element={<EditProduct />} />
</Routes>
</div>
</Router>
);
}
export default App;
index.jsを変更する
frontend/srcフォルダ内の, index.js を開きます。
下記の通り変更します。
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bulma/css/bulma.css';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
連携ができているか確認する
http://localhost:3000 へアクセスし、バックエンドとフロントエンドがしっかり連携できているか確認しましょう。
下記のような画面で、操作ができ、テーブルへレコードを追加するなどの動作が確認できれば終了です。
2記事に渡り、お疲れ様でした。
以上で終了です。