昨天將註冊API完成了。也用 postman 測試過 API可以正確註冊,接著我們今天來試試看吧API連接到APP畫面吧!。來看看APP要如何和後端使用API溝通。
今天不廢話,直接來上 Cursor。讓我們回到APP的專案。並詢問:
幫我在註冊頁面加上連接到 API,註冊的router是 http://localhost:3000/auth/register
[!Info] GPT回應
要在註冊頁面中連接到 API 進行註冊,你可以使用fetch
函數來發送 POST 請求到指定的路由。以下是修改後的Register.tsx
代碼,已經加入了 API 連接的邏輯:import React, { useState } from 'react'; import { NativeBaseProvider, Box, Input, Button, Text } from 'native-base'; import { Alert } from 'react-native'; const Register = ({ navigation }) => { const [username, setUsername] = useState(''); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [error, setError] = useState(''); const handleRegister = async () => { setError(''); if (!username || !email || !password || !confirmPassword) { setError('所有欄位都是必填的'); return; } if (password !== confirmPassword) { setError('密碼和確認密碼不一致'); return; } try { const response = await fetch('http://localhost:3000/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, email, password, }), }); const data = await response.json(); if (response.ok) { Alert.alert('註冊成功', '您已成功註冊!', [{ text: '確定', onPress: () => navigation.navigate('Login') }]); } else { setError(data.message || '註冊失敗,請稍後再試。'); } } catch (error) { setError('註冊時發生錯誤,請檢查您的網路連接。'); } }; return ( <Box flex={1} justifyContent="center" padding={4}> <Text fontSize="2xl" textAlign="center" marginBottom={4}>註冊</Text> {error ? <Text color="red.500" textAlign="center" marginBottom={3}>{error}</Text> : null} <Input placeholder="使用者名字" value={username} onChangeText={setUsername} marginBottom={3} /> <Input placeholder="信箱" value={email} onChangeText={setEmail} marginBottom={3} /> <Input placeholder="密碼" type="password" value={password} onChangeText={setPassword} marginBottom={3} /> <Input placeholder="確認密碼" type="password" value={confirmPassword} onChangeText={setConfirmPassword} marginBottom={3} /> <Button onPress={handleRegister}> 註冊 </Button> <Button onPress={() => navigation.navigate('Login')} marginTop={3}> 返回登入 </Button> </Box> ); }; export default Register;
在這段代碼中,我們使用
fetch
函數來發送 POST 請求到http://localhost:3000/auth/register
,並將使用者的註冊資訊作為 JSON 發送。如果註冊成功,則顯示成功的提示,否則顯示錯誤訊息。
我們點選Cusor 的套用,讓程式碼作用。接著到註冊面試試看。會發現出現 Inter Server Error,看起來像伺服器的錯誤。
我們回到API來查看一下是什麼錯誤。原來是我們送出的資料沒有 account。
看了後端的結果後知道是少了 Account這個欄位。那就把Account接上去吧。
抱歉 註冊的資料欄位是這些 { "username": "your_username", "email": "your_email@example.com", "password": "your_password", "account": "your_account" }
把 postman的測試資料直接貼上去,就算對AI也是要有禮貌的喔。這邊分享一個都市傳說,聽說對AI越有禮貌他回答會越認真越好。
[!Info] GPT回應
要在註冊頁面中更新資料欄位以包含account
,你需要在Register.tsx
中進行相應的修改。以下是更新後的代碼:import React, { useState } from 'react'; import { NativeBaseProvider, Box, Input, Button, Text } from 'native-base'; import { Alert } from 'react-native'; const Register = ({ navigation }) => { const [username, setUsername] = useState(''); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [account, setAccount] = useState(''); const [error, setError] = useState(''); const handleRegister = async () => { setError(''); if (!username || !email || !password || !confirmPassword || !account) { setError('所有欄位都是必填的'); return; } if (password !== confirmPassword) { setError('密碼和確認密碼不一致'); return; } try { const response = await fetch('http://localhost:3000/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, email, password, account, }), }); const data = await response.json(); if (response.ok) { Alert.alert('註冊成功', '您已成功註冊!', [{ text: '確定', onPress: () => navigation.navigate('Login') }]); } else { setError(data.message || '註冊失敗,請稍後再試。'); } } catch (error) { setError('註冊時發生錯誤,請檢查您的網路連接。'); } }; return ( <Box flex={1} justifyContent="center" padding={4}> <Text fontSize="2xl" textAlign="center" marginBottom={4}>註冊</Text> {error ? <Text color="red.500" textAlign="center" marginBottom={3}>{error}</Text> : null} <Input placeholder="使用者名字" value={username} onChangeText={setUsername} marginBottom={3} /> <Input placeholder="信箱" value={email} onChangeText={setEmail} marginBottom={3} /> <Input placeholder="密碼" type="password" value={password} onChangeText={setPassword} marginBottom={3} /> <Input placeholder="確認密碼" type="password" value={confirmPassword} onChangeText={setConfirmPassword} marginBottom={3} /> <Input placeholder="帳號" value={account} onChangeText={setAccount} marginBottom={3} /> <Button onPress={handleRegister}> 註冊 </Button> <Button onPress={() => navigation.navigate('Login')} marginTop={3}> 返回登入 </Button> </Box> ); }; export default Register;
在這段代碼中,我們新增了一個
account
的狀態,並在handleRegister
函數中將其包含在發送到 API 的請求中。同時也在 UI 中新增了一個輸入框來讓使用者填寫帳號。
讓他執行套用後,可以看到多了一個帳號的欄位。雖然他在畫面最下面很不科學啦,但這個之後可以自己手動調整沒關係。
接著來試試看註冊吧,輸入正確資訊後。直接出現 "註冊時發生錯誤,請假查你的網路連接" 這看起來更迷了。也不知是什麼問題。
多了帳號欄位 | 輸入資料後發生錯誤 |
一樣看一下後端的終端機,但沒有任何錯誤訊息。再來看看資料庫,咦,確實有多了一筆註冊資料。但這樣老實說也不太知道是什麼問題。不如問問看後端的 Cursor看看。
雖然是說應改可能是後端的問題,但我也不太知道問題是什麼。新增註冊的時候後端終端機不會報錯,看資料庫也確實有新增資料。💡不如直接把前端Code丟給後端的Cursor看看吧!?
try { const response = await fetch('http://localhost:3000/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, email, password, account, }), }); const data = await response.json(); if (response.ok) { Alert.alert('註冊成功', '您已成功註冊!', [{ text: '確定', onPress: () => navigation.navigate('Login') }]); } else { setError(data.message || '註冊失敗,請稍後再試。'); } } catch (error) { setError('註冊時發生錯誤,請檢查您的網路連接。'); } 幫我修改註冊api controll 的回應讓她不會跑到 error
[!Info] GPT回應
要修改註冊 API 控制器的回應,以確保在註冊成功時不會進入錯誤處理邏輯,你可以在AppController
的register
方法中,將成功的回應格式化為一個包含訊息的物件。這樣,前端就能夠正確地處理回應。以下是修改後的AppController
代碼:import { Controller, Post, Body } from '@nestjs/common'; import { AppService } from './app.service'; import { RegisterDto } from './dto/register.dto'; @Controller('auth') export class AppController { constructor(private readonly appService: AppService) {} @Post('register') async register(@Body() registerDto: RegisterDto): Promise<{ message: string }> { await this.appService.register(registerDto); return { message: '註冊成功' }; // 修改這裡,返回一個包含訊息的物件 } }
這樣修改後,當註冊成功時,API 將返回一個包含
message
的物件,前端可以根據這個訊息來判斷註冊是否成功,並且不會進入錯誤處理邏輯。
套用看看,再從前端發送註冊訊息。這次就成功了!!!
雖然我們用GPT幫我們解決了問題,但我們的目標是使用GPT先實作成功再學習,所以解決問題了,要來稍微看一下錯誤是什麼原因造成的。
原本的錯誤是因為在註冊 API 的回應中,當註冊成功時,返回的訊息格式不符合前端的預期。前端的代碼中有一段處理註冊回應的邏輯:
if (response.ok) {
Alert.alert('註冊成功', '您已成功註冊!', [{ text: '確定', onPress: () => navigation.navigate('Login') }]);
} else {
setError(data.message || '註冊失敗,請稍後再試。');
}
在這段代碼中,前端期望當註冊成功時,API 會返回一個 response.ok
為 true
的回應,並且能夠正確解析回應的內容。如果後端返回的內容不符合預期(例如,沒有返回 message
屬性),前端就會進入 else
區塊,並顯示錯誤訊息。
原本的後端代碼在註冊成功時只返回了一個字串 'User registered successfully'
,這樣的回應格式不符合前端的要求,導致前端無法正確處理成功的情況,進而進入錯誤處理邏輯。
透過修改後端的回應格式,讓它返回一個包含 message
屬性的物件,前端就能夠正確識別註冊是否成功,並顯示相應的提示。
我們今天一樣使用Cursor這個編輯器使用 GPT幫我們完成APP串接API連接到 BE的實作。
但我們在這之中遇到了一些問題,我們透過和GPT溝通解決問題。最後遇到一個雖然BE註冊成功,也有資料但是前端一樣顯示錯誤。
這其實是一個滿常見的前後端溝通不一致的情況。這也是我們一開始設計的時候沒有說的很仔細,和GPT的說明也不夠清楚造成的。
AI工具雖然好用,但是還是需要使用者明白知道要做什麼知道自己在做什麼,才能下明確的指令讓AI幫你完成工作。
又到了我們最後的工商時間啦~~~。Tom有在經營 Pocast,目前比較偏向職場類的閒聊,未來Podcast預計更新與程式軟體開發相關的主題。有興趣的朋友follow一下。
可以透過以下平台收聽: Apple podcast Spotify KKBOX
Linking Tree
#it鐵人