Skip to content

Commit

Permalink
feat: use SWR for part modules
Browse files Browse the repository at this point in the history
  • Loading branch information
SolidZORO committed Jul 29, 2020
1 parent daa5f32 commit 694f56c
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 92 deletions.
2 changes: 1 addition & 1 deletion packages/leaa-api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { envInfoForCli } from '@leaa/api/src/utils';
maxAge: 0,
optionsSuccessStatus: 200,
// methods: '',
allowedHeaders: ['Content-Type', 'Authorization', 'Guthorization'],
allowedHeaders: ['Content-Type', 'Authorization', 'Guthorization', 'Duthorization'],
exposedHeaders: ['Authorization'],
// preflightContinue: false,
});
Expand Down
1 change: 1 addition & 0 deletions packages/leaa-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"react-sortable-tree": "^2.7.1",
"react-test-renderer": "16.13.1",
"react-use": "^15.3.3",
"swr": "^0.2.3",
"uuid": "^8.3.0"
},
"devDependencies": {
Expand Down
4 changes: 4 additions & 0 deletions packages/leaa-dashboard/src/interfaces/http.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ export interface IHttpRes<T> extends AxiosResponse {
};
}

export interface IFetchRes<T> extends AxiosResponse {
data: T;
}

export interface IHttpError extends AxiosError {}
59 changes: 59 additions & 0 deletions packages/leaa-dashboard/src/libs/fetcher.lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// eslint-disable-next-line import/no-named-default
import { default as axiosLib } from 'axios';

import { getAuthToken, getGuestToken } from '@leaa/dashboard/src/utils';

export const fetcher = axiosLib;

fetcher.defaults.timeout = 10000;

fetcher.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
fetcher.defaults.headers.common.Authorization = getAuthToken() ? `Bearer ${getAuthToken()}` : '';
fetcher.defaults.headers.common.Guthorization = getGuestToken();
fetcher.defaults.headers.common.Duthorization = 'a';

// fetcher.interceptors.request.use(
// (res) => {
// // console.log('RRRRRRRR', res);
//
// return res;
// },
// (err) => {
// console.warn('❌ HTTP REQ ERROR', err);
//
// // ERROR Normalify statusCode > 400
// return Promise.resolve(err?.response);
// },
// );
//
// fetcher.interceptors.response.use(
// (res) => {
// console.log('XXXXXXXX?????????/', res);
//
// return res;
// },
// (err) => {
// // FINALLY
// console.warn('❌ HTTP RES ERROR', err);
//
// errorMsg(err.message);
//
// // TIMEOUT
// if (err?.code === 'ECONNABORTED') {
// // console.error('❌ HTTP RESPONSE TIMEOUT', error.response);
//
// return {
// data: err,
// status: 'timeout',
// };
// }
//
// // ERROR Normalify statusCode > 400
// return Promise.resolve(err?.response);
// },
// );

export const setAjaxToken = (token: string) => {
fetcher.defaults.headers.common.Authorization = `Bearer ${token}`;
console.log('🔑 Token is Updated.');
};
2 changes: 2 additions & 0 deletions packages/leaa-dashboard/src/libs/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './history.lib';
export * from './fetcher.lib';
export * from './use-fetch.lib';
67 changes: 67 additions & 0 deletions packages/leaa-dashboard/src/libs/use-fetch.lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import useSWR, { ConfigInterface, responseInterface } from 'swr';
import { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
import { ICrudListQueryParams } from '@leaa/dashboard/src/interfaces';

import { fetcher } from './fetcher.lib';

// extends axios
interface IAxiosRequestConfig extends AxiosRequestConfig {
crudQuery?: ICrudListQueryParams;
}

interface IAxiosResponse<T = any> extends AxiosResponse {
config: IAxiosRequestConfig;
}

interface IReturn<Data, Error>
extends Pick<
responseInterface<IAxiosResponse<Data>, AxiosError<Error>>,
'isValidating' | 'revalidate' | 'error' | 'mutate'
> {
data: Data | undefined;
loading?: boolean;
response?: IAxiosResponse<Data> | undefined;
}

export interface IConfig<Data = unknown, Error = unknown>
extends Omit<ConfigInterface<IAxiosResponse<Data>, AxiosError<Error>>, 'initialData'> {
initialData?: Data;
}

export function useFetch<Data = unknown, Error = unknown>(
request: IAxiosRequestConfig | null,
{ initialData, ...config }: IConfig<Data, Error> = {},
): IReturn<Data, Error> {
const { data: response, error, isValidating, revalidate, mutate } = useSWR<AxiosResponse<Data>, AxiosError<Error>>(
request?.url ? JSON.stringify(request) : null,
/**
* NOTE: Typescript thinks `request` can be `null` here, but the fetcher
* function is actually only called by `useSWR` when it isn't.
*/
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(): any => fetcher(request!),
{
revalidateOnFocus: false,
// revalidateOnReconnect: false,
initialData: initialData && {
status: 200,
statusText: 'InitialData',
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
config: request!,
headers: {},
data: initialData,
},
...config,
},
);

return {
data: response?.data,
// response,
error,
isValidating,
loading: isValidating,
revalidate,
mutate,
};
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import _ from 'lodash';
import cx from 'classnames';
import { Tag } from 'antd';
import { Button } from 'antd';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMount, useUpdateEffect } from 'react-use';
import { useUpdateEffect } from 'react-use';

import { Ax } from '@leaa/api/src/entrys';
import { envConfig } from '@leaa/dashboard/src/configs';
import { DEFAULT_QUERY } from '@leaa/dashboard/src/constants';
import { IPage, ICrudListQueryParams, IHttpRes, ICrudListRes, IHttpError } from '@leaa/dashboard/src/interfaces';
import { IPage, ICrudListQueryParams, ICrudListRes, IFetchRes } from '@leaa/dashboard/src/interfaces';
import {
ajax,
errorMsg,
setCrudQueryToUrl,
transUrlQueryToCrudState,
genCrudRequestQuery,
genCrudQuerySearch,
} from '@leaa/dashboard/src/utils';
import { PageCard, HtmlMeta, TableCard, SearchInput } from '@leaa/dashboard/src/components';
import { useFetch } from '@leaa/dashboard/src/libs';

import style from './style.module.less';

Expand All @@ -28,30 +28,27 @@ export default (props: IPage) => {

const [crudQuery, setCrudQuery] = useState<ICrudListQueryParams>({
...DEFAULT_QUERY,
...transUrlQueryToCrudState(window),
sort: ['created_at', 'DESC'],
...transUrlQueryToCrudState(window),
});

const [list, setList] = useState<ICrudListRes<Ax>>();
const [listLoading, setListLoading] = useState(false);
const onFetchList = (params: ICrudListQueryParams) => {
setCrudQuery(params);
setListLoading(true);

ajax
.get(`${envConfig.API_URL}/${envConfig.API_VERSION}/${API_PATH}`, { params: genCrudRequestQuery(params) })
.then((res: IHttpRes<ICrudListRes<Ax>>) => {
setList(res.data.data);

setCrudQueryToUrl({ window, query: params, replace: true });
})
.catch((err: IHttpError) => errorMsg(err.response?.data?.message || err.message))
.finally(() => setListLoading(false));
};
const list = useFetch<IFetchRes<ICrudListRes<Ax>>>(
{
method: 'GET',
url: `${envConfig.API_URL}/${envConfig.API_VERSION}/${API_PATH}`,
params: genCrudRequestQuery(crudQuery),
crudQuery,
},
{
onError: (err) => errorMsg(err.message),
onSuccess: (res) => setCrudQueryToUrl({ window, query: res.config.crudQuery, replace: true }),
},
);

useMount(() => onFetchList(crudQuery));
useUpdateEffect(() => onFetchList(DEFAULT_QUERY), [props.history.location.key]);
useUpdateEffect(() => (!_.isEqual(crudQuery, DEFAULT_QUERY) ? onFetchList(crudQuery) : undefined), [crudQuery]);
useUpdateEffect(() => {
if (_.isEqual(crudQuery, DEFAULT_QUERY)) list.mutate();
else setCrudQuery(DEFAULT_QUERY);
}, [props.history.location.key]);

return (
<PageCard
Expand All @@ -75,11 +72,11 @@ export default (props: IPage) => {
/>
}
className={style['wapper']}
loading={listLoading}
loading={list.loading}
>
<HtmlMeta title={t(`${props.route?.namei18n}`)} />

{list?.data && (
{list.data?.data && (
<TableCard
crudQuery={crudQuery}
setCrudQuery={setCrudQuery}
Expand Down Expand Up @@ -110,7 +107,7 @@ export default (props: IPage) => {
'status',
{ action: { fieldName: 'title' } },
]}
list={list}
list={list.data?.data}
/>
)}
</PageCard>
Expand Down
46 changes: 17 additions & 29 deletions packages/leaa-dashboard/src/pages/Tag/TagEdit/TagEdit.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useState, useRef, useEffect } from 'react';
import React, { useState, useRef } from 'react';
import { useTranslation } from 'react-i18next';

import { Tag } from '@leaa/api/src/entrys';
import { TagUpdateOneReq } from '@leaa/api/src/dtos/tag';
import { IPage, ICommenFormRef, ISubmitData, IHttpRes, IHttpError } from '@leaa/dashboard/src/interfaces';
import { msg, errorMsg, ajax } from '@leaa/dashboard/src/utils';
import { IPage, ICommenFormRef, ISubmitData, IHttpRes, IHttpError, IFetchRes } from '@leaa/dashboard/src/interfaces';
import { msg, errorMsg, setCrudQueryToUrl } from '@leaa/dashboard/src/utils';
import { useFetch, fetcher } from '@leaa/dashboard/src/libs';
import { envConfig } from '@leaa/dashboard/src/configs';

import { PageCard, HtmlMeta, SubmitToolbar } from '@leaa/dashboard/src/components';
Expand All @@ -20,53 +21,40 @@ export default (props: IPage) => {
const { id } = props.match.params as { id: string };

const infoFormRef = useRef<ICommenFormRef<TagUpdateOneReq>>(null);

const [item, setItem] = useState<Tag | undefined>();
const [itemLoading, setItemLoading] = useState(false);
const [submitLoading, setSubmitLoading] = useState(false);

const onFetchItem = () => {
setItemLoading(true);

ajax
.get(`${envConfig.API_URL}/${envConfig.API_VERSION}/${API_PATH}/${id}`)
.then((res: IHttpRes<Tag>) => {
setItem(res.data.data);
})
.catch((err: IHttpError) => errorMsg(err.response?.data?.message || err.message))
.finally(() => setItemLoading(false));
};
const item = useFetch<IFetchRes<Tag>>(
{ url: `${envConfig.API_URL}/${envConfig.API_VERSION}/${API_PATH}/${id}` },
{
onError: (err) => errorMsg(err.message),
onSuccess: (res) => setCrudQueryToUrl({ window, query: res.config.crudQuery, replace: true }),
},
);

const onUpdateItem = async () => {
const infoData: ISubmitData<TagUpdateOneReq> = await infoFormRef.current?.onValidateForm();

if (!infoData) return;

const data: ISubmitData<TagUpdateOneReq> = {
...infoData,
};

const data: ISubmitData<TagUpdateOneReq> = { ...infoData };
setSubmitLoading(true);

ajax
fetcher
.patch(`${envConfig.API_URL}/${envConfig.API_VERSION}/${API_PATH}/${id}`, data)
.then((res: IHttpRes<Tag>) => {
setItem(res.data.data);
.then((res: IFetchRes<Tag>) => {
item.mutate(res, false);

msg(t('_lang:updatedSuccessfully'));
})
.catch((err: IHttpError) => errorMsg(err.response?.data?.message || err.message))
.finally(() => setSubmitLoading(false));
};

// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => onFetchItem(), []);

return (
<PageCard route={props.route} title="@UPDATE" className={style['wapper']} loading={itemLoading || submitLoading}>
<PageCard route={props.route} title="@UPDATE" className={style['wapper']} loading={item.loading || submitLoading}>
<HtmlMeta title={t(`${props.route?.namei18n}`)} />

<TagInfoForm item={item} loading={itemLoading} ref={infoFormRef} />
<TagInfoForm item={item?.data?.data} loading={item.loading} ref={infoFormRef} />

<SubmitToolbar
simpleButtonGroup={{ title: '@UPDATE', loading: submitLoading }}
Expand Down
Loading

0 comments on commit 694f56c

Please sign in to comment.