前幾天我們實作了會員系統,Api和使用 postman驗證的部分。使用 cursor雖然可以很快的把城市寫出來。但是還是會需要修改。
今天我們就把前幾天的做的 api 串接到前端。這個部分就可以參考前幾天 註冊串接 api 的部分。其實串接 api 滿累的,有時候滿像在做一樣的事。不過前提是架構設計的好。
因為其實大家可以使用 Cursor 請他幫我們實作,故我這邊大概寫一下做法就好了。
在 src/lib/store.ts
中創建 Redux store:
import { configureStore } from '@reduxjs/toolkit';
import userReducer from '../Redux/Reducers/userReducer';
const store = configureStore({
reducer: {
user: userReducer,
},
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export default store;
在 src/Redux/Reducers/userReducer.ts
中創建用戶 reducer,在這邊把我們的 AIP路徑寫上去。
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import api from '../../lib/configAxios';
export const loginUser = createAsyncThunk('user/login', async (credentials) => {
const response = await api.post('/login', credentials);
return response.data;
});
export const fetchUserInfo = createAsyncThunk('user/fetchInfo', async (userId) => {
const response = await api.get(`/users/${userId}`);
return response.data;
});
export const updateUserInfo = createAsyncThunk('user/updateInfo', async (data) => {
const response = await api.put(`/users/${data.userId}`, data);
return response.data;
});
const userSlice = createSlice({
name: 'user',
initialState: {
userInfo: null,
loading: false,
error: null,
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(loginUser.fulfilled, (state, action) => {
state.userInfo = action.payload;
})
.addCase(fetchUserInfo.fulfilled, (state, action) => {
state.userInfo = action.payload;
})
.addCase(updateUserInfo.fulfilled, (state, action) => {
state.userInfo = { ...state.userInfo, ...action.payload };
});
},
});
export default userSlice.reducer;
在 登入頁面中引用登入 api函數。登入後取得的 token,要寫在發送 api 的中間件帶入(待補充)。
const handleLogin = () => {
dispatch(loginUser({ username, password }));
};
import React, { useState } from 'react';
import { View, Text, Button, Input, VStack, FormControl } from 'native-base';
import { useDispatch } from 'react-redux';
import { loginUser } from '../../Redux/Reducers/userReducer';
const LoginPage = () => {
const dispatch = useDispatch();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleLogin = () => {
dispatch(loginUser({ username, password }));
};
return (
<View>
<VStack space={4}>
<FormControl>
<FormControl.Label>Username</FormControl.Label>
<Input value={username} onChangeText={setUsername} />
</FormControl>
<FormControl>
<FormControl.Label>Password</FormControl.Label>
<Input type="password" value={password} onChangeText={setPassword} />
</FormControl>
<Button onPress={handleLogin}>Login</Button>
</VStack>
</View>
);
};
export default LoginPage;
可以請Cursor base on native-base 套件幫我們做一下頁面。但這邊要記得飲用取得會員資料(getUserInfo) 和修改會用資料API(updateUserInfo)。
這邊表單的填寫,建議使用 fromControl,一樣可以對 AI 下提示詞請他實作。
import React, {useEffect, useState} from 'react';
import {View, Text, Button, Input, VStack, FormControl} from 'native-base';
import {useDispatch, useSelector} from 'react-redux';
import {getUserInfo, updateUserInfo} from '../../Redux/Thunks/userThunks';
import {RootState} from '../../lib/store';
import styles from './styles';
const UserInfoPage = () => {
const dispatch = useDispatch();
const user = useSelector((state: RootState) => state.user);
const [username, setUsername] = useState(user.username);
const [email, setEmail] = useState(user.email);
const [account, setAccount] = useState(user.account);
useEffect(() => {
dispatch(getUserInfo({userId: user.userId,}));
}, [dispatch, user.userId);
const handleUpdate = () => {
dispatch(
updateUserInfo({
userId: user.userId,
data: {username, email, account},
}),
);
};
return (
<View style={styles.centered}>
<VStack space={4} width="90%">
<Text style={styles.title}>User Info</Text>
<FormControl>
<FormControl.Label>Username</FormControl.Label>
<Input
placeholder="Username"
value={username}
onChangeText={setUsername}
/>
</FormControl>
<FormControl>
<FormControl.Label>Email</FormControl.Label>
<Input placeholder="Email" value={email} onChangeText={setEmail} />
</FormControl>
<FormControl>
<FormControl.Label>Account</FormControl.Label>
<Input
placeholder="Account"
value={account}
onChangeText={setAccount}
/>
</FormControl>
<Button onPress={handleUpdate}>Submit</Button>
</VStack>
</View>
);
};
export default UserInfoPage;
在 Router 中設定各個頁面的路由
........
<Stack.Navigator initialRouteName={initialRoute}>
<Stack.Screen
name={RouteNames.HomePage}
component={HomePage}
options={{headerShown: false}}
listeners={{
focus: checkToken,
}}
/>
<Stack.Screen
name={RouteNames.Login}
component={LoginPage}
options={{headerShown: false}}
/>
<Stack.Screen name={RouteNames.Register} component={RegisterPage} />
<Stack.Screen name={RouteNames.UserInfoPage} component={UserInfoPage} />
<Stack.Screen
name={RouteNames.CreateReportPage}
options={{headerShown: false}}
component={CreateReportPage}
/>
<Stack.Screen name={RouteNames.ReportPage} component={ReportPage} />
<Stack.Screen name={RouteNames.FormExample} component={FormExamplePage} />
<Stack.Screen
name={RouteNames.ReportListPage}
component={ReportListPage}
/>
<Stack.Screen name={RouteNames.PDFPage} component={PDFViewer} />
</Stack.Navigator>
........
今天頁面稍微不一樣,因為我之前是開新範例,今天是回去修改之前的檔案。頁面會看起來像是這樣。
![[Pasted image 20241005232344.png]] | ||
---|---|---|
登入頁面 | 註冊頁面 | 使用者資訊 |
實作的部分我覺得貼太多AI回應好像不太有意思,我講一下大概和要點,希望大家可以知道怎麼時和AI溝通的概念。自己實作的時候就可以知道怎麼做。
但如果真的有需要,之後我可以再提供簡單的範例實作檔案。
明天會開始進入表單填寫的部分設計。