fix: Login with @tanstack/react-query #1306 (#1691)

### What problem does this PR solve?

fix: Login with @tanstack/react-query #1306

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
balibabu 2024-07-24 18:02:58 +08:00 committed by GitHub
parent 32d5885b68
commit 7ca98848ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 85 additions and 125 deletions

View File

@ -1,5 +1,10 @@
import { useCallback } from 'react';
import { useDispatch } from 'umi';
import { Authorization } from '@/constants/authorization';
import userService from '@/services/user-service';
import authorizationUtil from '@/utils/authorizationUtil';
import { useMutation } from '@tanstack/react-query';
import { message } from 'antd';
import { useTranslation } from 'react-i18next';
import { history } from 'umi';
export interface ILoginRequestBody {
email: string;
@ -11,34 +16,82 @@ export interface IRegisterRequestBody extends ILoginRequestBody {
}
export const useLogin = () => {
const dispatch = useDispatch();
const { t } = useTranslation();
const login = useCallback(
(requestBody: ILoginRequestBody) => {
// TODO: Type needs to be improved
return dispatch<any>({
type: 'loginModel/login',
payload: requestBody,
});
const {
data,
isPending: loading,
mutateAsync,
} = useMutation({
mutationKey: ['login'],
mutationFn: async (params: { email: string; password: string }) => {
const { data: res = {}, response } = await userService.login(params);
if (res.retcode === 0) {
const { data } = res;
message.success(t('message.logged'));
const authorization = response.headers.get(Authorization);
const token = data.access_token;
const userInfo = {
avatar: data.avatar,
name: data.nickname,
email: data.email,
};
authorizationUtil.setItems({
Authorization: authorization,
userInfo: JSON.stringify(userInfo),
Token: token,
});
}
return res.retcode;
},
[dispatch],
);
});
return login;
return { data, loading, login: mutateAsync };
};
export const useRegister = () => {
const dispatch = useDispatch();
const { t } = useTranslation();
const register = useCallback(
(requestBody: IRegisterRequestBody) => {
return dispatch<any>({
type: 'loginModel/register',
payload: requestBody,
});
const {
data,
isPending: loading,
mutateAsync,
} = useMutation({
mutationKey: ['register'],
mutationFn: async (params: {
email: string;
password: string;
nickname: string;
}) => {
const { data = {} } = await userService.register(params);
if (data.retcode === 0) {
message.success(t('message.registered'));
}
return data.retcode;
},
[dispatch],
);
});
return register;
return { data, loading, register: mutateAsync };
};
export const useLogout = () => {
const { t } = useTranslation();
const {
data,
isPending: loading,
mutateAsync,
} = useMutation({
mutationKey: ['logout'],
mutationFn: async () => {
const { data = {} } = await userService.logout();
if (data.retcode === 0) {
message.success(t('message.logout'));
authorizationUtil.removeAll();
history.push('/login');
}
return data.retcode;
},
});
return { data, loading, logout: mutateAsync };
};

View File

@ -1,9 +1,8 @@
import { ITenantInfo } from '@/interfaces/database/knowledge';
import { ISystemStatus, IUserInfo } from '@/interfaces/database/userSetting';
import userService from '@/services/user-service';
import authorizationUtil from '@/utils/authorizationUtil';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { history, useDispatch, useSelector } from 'umi';
import { useDispatch, useSelector } from 'umi';
export const useFetchUserInfo = () => {
const dispatch = useDispatch();
@ -67,20 +66,6 @@ export const useSelectParserList = (): Array<{
return parserList;
};
export const useLogout = () => {
const dispatch = useDispatch(); // TODO: clear redux state
const logout = useCallback(async () => {
const retcode = await dispatch<any>({ type: 'loginModel/logout' });
if (retcode === 0) {
authorizationUtil.removeAll();
history.push('/login');
}
}, [dispatch]);
return logout;
};
export const useSaveSetting = () => {
const dispatch = useDispatch();

View File

@ -1,5 +1,4 @@
import { useLogin, useRegister } from '@/hooks/login-hooks';
import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks';
import { rsaPsw } from '@/utils';
import { Button, Checkbox, Form, Input } from 'antd';
import { useEffect, useState } from 'react';
@ -13,16 +12,10 @@ import styles from './index.less';
const Login = () => {
const [title, setTitle] = useState('login');
const navigate = useNavigate();
const login = useLogin();
const register = useRegister();
const { login, loading: signLoading } = useLogin();
const { register, loading: registerLoading } = useRegister();
const { t } = useTranslation('translation', { keyPrefix: 'login' });
// TODO: When the server address request is not accessible, the value of dva-loading always remains true.
const signLoading = useOneNamespaceEffectsLoading('loginModel', [
'login',
'register',
]);
const loading = signLoading || registerLoading;
const changeTitle = () => {
setTitle((title) => (title === 'login' ? 'register' : 'login'));
@ -148,7 +141,7 @@ const Login = () => {
block
size="large"
onClick={onCheck}
loading={signLoading}
loading={loading}
>
{title === 'login' ? t('login') : t('continue')}
</Button>

View File

@ -1,69 +0,0 @@
import { Authorization } from '@/constants/authorization';
import i18n from '@/locales/config';
import userService from '@/services/user-service';
import authorizationUtil from '@/utils/authorizationUtil';
import { message } from 'antd';
import { DvaModel } from 'umi';
export interface LoginModelState {
list: any[];
info: any;
visible: boolean;
}
const model: DvaModel<LoginModelState> = {
namespace: 'loginModel',
state: {
list: [],
info: {},
visible: false,
},
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload,
};
},
},
effects: {
*login({ payload = {} }, { call }) {
const { data, response } = yield call(userService.login, payload);
const { retcode, data: res } = data;
const authorization = response.headers.get(Authorization);
if (retcode === 0) {
message.success(i18n.t('message.logged'));
const token = res.access_token;
const userInfo = {
avatar: res.avatar,
name: res.nickname,
email: res.email,
};
authorizationUtil.setItems({
Authorization: authorization,
userInfo: JSON.stringify(userInfo),
Token: token,
});
}
return retcode;
},
*register({ payload = {} }, { call }) {
const { data } = yield call(userService.register, payload);
console.log();
const { retcode } = data;
if (retcode === 0) {
message.success(i18n.t('message.registered'));
}
return retcode;
},
*logout({ payload = {} }, { call }) {
const { data } = yield call(userService.logout, payload);
const { retcode } = data;
if (retcode === 0) {
message.success(i18n.t('message.logout'));
}
return retcode;
},
},
};
export default model;

View File

@ -1,5 +1,8 @@
import { Domain } from '@/constants/common';
import { useTranslate } from '@/hooks/common-hooks';
import { useLogout } from '@/hooks/login-hooks';
import { useSecondPathName } from '@/hooks/route-hook';
import { useFetchSystemVersion } from '@/hooks/user-setting-hooks';
import type { MenuProps } from 'antd';
import { Flex, Menu } from 'antd';
import React, { useEffect, useMemo } from 'react';
@ -9,9 +12,6 @@ import {
UserSettingIconMap,
UserSettingRouteKey,
} from '../constants';
import { useTranslate } from '@/hooks/common-hooks';
import { useFetchSystemVersion, useLogout } from '@/hooks/user-setting-hooks';
import styles from './index.less';
type MenuItem = Required<MenuProps>['items'][number];
@ -19,7 +19,7 @@ type MenuItem = Required<MenuProps>['items'][number];
const SideBar = () => {
const navigate = useNavigate();
const pathName = useSecondPathName();
const logout = useLogout();
const { logout } = useLogout();
const { t } = useTranslate('setting');
const { version, fetchSystemVersion } = useFetchSystemVersion();

2
web/typings.d.ts vendored
View File

@ -3,7 +3,6 @@ import { KFModelState } from '@/pages/add-knowledge/components/knowledge-file/mo
import { TestingModelState } from '@/pages/add-knowledge/components/knowledge-testing/model';
import { kAModelState } from '@/pages/add-knowledge/model';
import { ChatModelState } from '@/pages/chat/model';
import { LoginModelState } from '@/pages/login/model';
import { SettingModelState } from '@/pages/user-setting/model';
declare module 'lodash';
@ -15,7 +14,6 @@ function useSelector<TState = RootState, TSelected = unknown>(
export interface RootState {
chatModel: ChatModelState;
loginModel: LoginModelState;
settingModel: SettingModelState;
kFModel: KFModelState;
kAModel: kAModelState;