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 { Authorization } from '@/constants/authorization';
import { useDispatch } from 'umi'; 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 { export interface ILoginRequestBody {
email: string; email: string;
@ -11,34 +16,82 @@ export interface IRegisterRequestBody extends ILoginRequestBody {
} }
export const useLogin = () => { export const useLogin = () => {
const dispatch = useDispatch(); const { t } = useTranslation();
const login = useCallback( const {
(requestBody: ILoginRequestBody) => { data,
// TODO: Type needs to be improved isPending: loading,
return dispatch<any>({ mutateAsync,
type: 'loginModel/login', } = useMutation({
payload: requestBody, 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 = () => { export const useRegister = () => {
const dispatch = useDispatch(); const { t } = useTranslation();
const register = useCallback( const {
(requestBody: IRegisterRequestBody) => { data,
return dispatch<any>({ isPending: loading,
type: 'loginModel/register', mutateAsync,
payload: requestBody, } = 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 { ITenantInfo } from '@/interfaces/database/knowledge';
import { ISystemStatus, IUserInfo } from '@/interfaces/database/userSetting'; import { ISystemStatus, IUserInfo } from '@/interfaces/database/userSetting';
import userService from '@/services/user-service'; import userService from '@/services/user-service';
import authorizationUtil from '@/utils/authorizationUtil';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { history, useDispatch, useSelector } from 'umi'; import { useDispatch, useSelector } from 'umi';
export const useFetchUserInfo = () => { export const useFetchUserInfo = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -67,20 +66,6 @@ export const useSelectParserList = (): Array<{
return parserList; 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 = () => { export const useSaveSetting = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();

View File

@ -1,5 +1,4 @@
import { useLogin, useRegister } from '@/hooks/login-hooks'; import { useLogin, useRegister } from '@/hooks/login-hooks';
import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks';
import { rsaPsw } from '@/utils'; import { rsaPsw } from '@/utils';
import { Button, Checkbox, Form, Input } from 'antd'; import { Button, Checkbox, Form, Input } from 'antd';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
@ -13,16 +12,10 @@ import styles from './index.less';
const Login = () => { const Login = () => {
const [title, setTitle] = useState('login'); const [title, setTitle] = useState('login');
const navigate = useNavigate(); const navigate = useNavigate();
const login = useLogin(); const { login, loading: signLoading } = useLogin();
const register = useRegister(); const { register, loading: registerLoading } = useRegister();
const { t } = useTranslation('translation', { keyPrefix: 'login' }); const { t } = useTranslation('translation', { keyPrefix: 'login' });
const loading = signLoading || registerLoading;
// TODO: When the server address request is not accessible, the value of dva-loading always remains true.
const signLoading = useOneNamespaceEffectsLoading('loginModel', [
'login',
'register',
]);
const changeTitle = () => { const changeTitle = () => {
setTitle((title) => (title === 'login' ? 'register' : 'login')); setTitle((title) => (title === 'login' ? 'register' : 'login'));
@ -148,7 +141,7 @@ const Login = () => {
block block
size="large" size="large"
onClick={onCheck} onClick={onCheck}
loading={signLoading} loading={loading}
> >
{title === 'login' ? t('login') : t('continue')} {title === 'login' ? t('login') : t('continue')}
</Button> </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 { Domain } from '@/constants/common';
import { useTranslate } from '@/hooks/common-hooks';
import { useLogout } from '@/hooks/login-hooks';
import { useSecondPathName } from '@/hooks/route-hook'; import { useSecondPathName } from '@/hooks/route-hook';
import { useFetchSystemVersion } from '@/hooks/user-setting-hooks';
import type { MenuProps } from 'antd'; import type { MenuProps } from 'antd';
import { Flex, Menu } from 'antd'; import { Flex, Menu } from 'antd';
import React, { useEffect, useMemo } from 'react'; import React, { useEffect, useMemo } from 'react';
@ -9,9 +12,6 @@ import {
UserSettingIconMap, UserSettingIconMap,
UserSettingRouteKey, UserSettingRouteKey,
} from '../constants'; } from '../constants';
import { useTranslate } from '@/hooks/common-hooks';
import { useFetchSystemVersion, useLogout } from '@/hooks/user-setting-hooks';
import styles from './index.less'; import styles from './index.less';
type MenuItem = Required<MenuProps>['items'][number]; type MenuItem = Required<MenuProps>['items'][number];
@ -19,7 +19,7 @@ type MenuItem = Required<MenuProps>['items'][number];
const SideBar = () => { const SideBar = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const pathName = useSecondPathName(); const pathName = useSecondPathName();
const logout = useLogout(); const { logout } = useLogout();
const { t } = useTranslate('setting'); const { t } = useTranslate('setting');
const { version, fetchSystemVersion } = useFetchSystemVersion(); 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 { TestingModelState } from '@/pages/add-knowledge/components/knowledge-testing/model';
import { kAModelState } from '@/pages/add-knowledge/model'; import { kAModelState } from '@/pages/add-knowledge/model';
import { ChatModelState } from '@/pages/chat/model'; import { ChatModelState } from '@/pages/chat/model';
import { LoginModelState } from '@/pages/login/model';
import { SettingModelState } from '@/pages/user-setting/model'; import { SettingModelState } from '@/pages/user-setting/model';
declare module 'lodash'; declare module 'lodash';
@ -15,7 +14,6 @@ function useSelector<TState = RootState, TSelected = unknown>(
export interface RootState { export interface RootState {
chatModel: ChatModelState; chatModel: ChatModelState;
loginModel: LoginModelState;
settingModel: SettingModelState; settingModel: SettingModelState;
kFModel: KFModelState; kFModel: KFModelState;
kAModel: kAModelState; kAModel: kAModelState;