在昨天的練習中,我們成功學會修改畫面,建置表單的名稱,但我相信各位一定覺得少了一點什麼,平常看到的畫面都是有欄位框框、以及按下Submit會有反應,而現在,我們就要來建立這些動作
這個時候,我們就開始進入我們的挑戰,開發前端後端整合的第一個功能!
跟Spring boot一樣,React也有Service層,這層的主要功能是把對於後端API的服務都整合一起,方便我們取用。所以我們要先在src底下,新建一個Service的資料夾。
在創建了Service裡面,再新增一個AccountService.js。
雖然我們用JS來操作與後端的連線,但是連線不只能靠JS,還需要其他的功能,這個時候我們就要額外安裝一個dependency來呼叫API,我們可以先去到終端機,然後輸入
npm install axios
安裝的時候請確認移動到Account-frontend,不然安裝成功之後仍然沒有用唷
在安裝完成之後, 需要到package.json中確認是否已經安裝裝了這個功能
在React中,axios是一個用來發送HTTP請求的第三方JS庫,主要功能是與後端服務進行通訊。axios可以讓我們方便向API發送GET、POST、PUT、DELETE等請求,並處理回應數據。axios很適合處理異步操作,讓程式碼結構更清晰。
我們重新回到AccountService.js中,先用import匯入axios,然後我們要設置一個變數,用來存儲Spring boot的API網址,接下來,我們要寫一個addAccount的功能
import axios from "axios";
const BASE_REST_API_URL = "http://localhost:8080/api/accounts"
export const addAccount = (account) => axios.post(BASE_REST_API_URL,account);
這裡的addAccount是一行指令,指的是我們需要匯入(account)這個變數,然後就要使用axios的Post,路徑就是我們先前設置的變數,要post的就是account這個資料。
JS方便的地方就是我們不用宣告這個變數是什麼型態,只要丟正確了,就能夠順利執行。
然後我們回到AccountComponent.jsx這個頁面
接下來,我們要先匯入
import React, { useState } from 'react'
import { addAccount } from '../Service/AccountService'
這兩個就是我們接下來要使用到的,整個React的設計邏輯比較像這樣
在Html網頁上面,就是屬於功能的類別,我們需要把我們要做的操作都放在上面,而一開始我們要宣告在這個頁面裡面我們會改變到的參數是什麼,需要用到useState('')這個功能,這也是我們需要import的功能之一,我們要輸入帳目名稱、帳目類別、帳目金額、支出收入,所以要先宣告這些變數在前面
const [name, setName] = useState('')
const [category,setCategory] = useState('')
const [amount,setAmount] = useState('')
const [expensed,setExpensed] = useState(false)
然後我們就要建立存檔的功能,讓我們按下submit之後會觸發,我們可以用saveAccount來當作function名稱,程式碼如下,我們要使用到Service的addAccount功能,載我們輸入add之後,其實就能夠看到插件幫我們先寫出來了這個要引用的部分,只要按下確定,程式就會自動幫我們import這個功能進來。
接下來,完整的程式如下
function saveAccount(e){
e.preventDefault()
const account = {name,category,amount,expensed}
console.log(account)
//將資料傳給後端
addAccount(account).then((response)=>{
console.log(response.data)
}).catch(error =>{
console.log(error)
}
)
完成之後,我們就要來修改html的程式碼
return (
<div className='container'>
<br></br>
<div className='card col-md-6 offest-md-3 offset-md-3'>
<br></br>
<h2 className='text-center'>Add Todo</h2>
<div className='card-body'>
<form>
<div className='form-group mb-2 text-center'>
<label className='form-label'>Account Title</label>
<input
type='text'
className='form-control'
placeholder='Enter Account Name'
value={(name)}
onChange={(e)=>setName(e.target.value)}
></input>
</div>
<div className='form-group mb-2 text-center'>
<label className='form-label'>Account Category:</label>
<input
type='text'
className='form-control'
placeholder='Enter Account Category'
value={(category)}
onChange={(e)=>setCategory(e.target.value)}
></input>
</div>
<div className='form-group mb-2 text-center'>
<label className='form-label'>Account Amount:</label>
<input
type='text'
className='form-control'
placeholder='Enter Account Amount'
value={(amount)}
onChange={(e)=>setAmount(e.target.value)}
></input>
</div>
<div className='form-group mb-2 text-center'>
<label className='form-label'>Account expense:</label>
<select
className='form-control'
value={expensed}
onChange={(e)=> setExpensed(e.target.value)}
>
<option value='false'>支出</option>
<option value='true'>收入</option>
</select>
</div>
<button className='btn btn-success' onClick={(e)=>saveAccount(e)}>Submit</button>
</form>
</div>
</div>
</div>
)
完成之後,存檔就會看到畫面變成這樣,大家記得同時也啟動Spring boot讓後端可以接收命令
這個時候我們輸入資料,按下submit會出現問題,這是因為Spring boot因為CORS關係拒絕前端呼叫
因為Cross的關係,所以我們只要回到我們的Spring boot,然後進入Controller層,新增@CrossOrigin(*),存檔之後重新啟動Spring boot
@CrossOrigin("*")
@RestController
@RequestMapping("/api/accounts")
public class AccountController {
這個時候在前端再輸入submit之後,就會出現回傳的response
這個時候我們再回到資料庫中,就會發現我們新增了這筆資料
到了這裡,恭喜大家打通了任督二脈,從後端開發到前端,又成功的把前端的資料輸入進後端中!