iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
Mobile Development

30天 使用chatGPT輔助學習APP完成接案任務委託系列 第 21

[Day21]API 串接 Redux Toolkit:串接會員系統與頁面實作

  • 分享至 

  • xImage
  •  

前幾天我們實作了會員系統,Api和使用 postman驗證的部分。使用 cursor雖然可以很快的把城市寫出來。但是還是會需要修改。

今天我們就把前幾天的做的 api 串接到前端。這個部分就可以參考前幾天 註冊串接 api 的部分。其實串接 api 滿累的,有時候滿像在做一樣的事。不過前提是架構設計的好。

因為其實大家可以使用 Cursor 請他幫我們實作,故我這邊大概寫一下做法就好了。

Redux 設定

1. Redux Store

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;

2. 創建 User Reducer

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溝通的概念。自己實作的時候就可以知道怎麼做。

但如果真的有需要,之後我可以再提供簡單的範例實作檔案。

明天會開始進入表單填寫的部分設計。


上一篇
[DAY20] 確認與驗證AI生成的會員功能
下一篇
[Day22] React Native APP Token 認證相關
系列文
30天 使用chatGPT輔助學習APP完成接案任務委託30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言