From 694f56c8df0fb8ab0b2dc1cbd92aa22b76f333e8 Mon Sep 17 00:00:00 2001 From: SolidZORO Date: Wed, 29 Jul 2020 17:54:47 +0800 Subject: [PATCH] feat: use SWR for part modules --- packages/leaa-api/src/main.ts | 2 +- packages/leaa-dashboard/package.json | 1 + .../src/interfaces/http.interface.ts | 4 ++ .../leaa-dashboard/src/libs/fetcher.lib.ts | 59 ++++++++++++++++ packages/leaa-dashboard/src/libs/index.ts | 2 + .../leaa-dashboard/src/libs/use-fetch.lib.ts | 67 +++++++++++++++++++ .../AttachmentList/AttachmentList.tsx | 51 +++++++------- .../src/pages/Tag/TagEdit/TagEdit.tsx | 46 +++++-------- .../src/pages/Tag/TagList/TagList.tsx | 63 ++++++++--------- .../TestAnyWithoutLayout.tsx | 11 +++ yarn.lock | 12 ++++ 11 files changed, 226 insertions(+), 92 deletions(-) create mode 100644 packages/leaa-dashboard/src/libs/fetcher.lib.ts create mode 100644 packages/leaa-dashboard/src/libs/use-fetch.lib.ts diff --git a/packages/leaa-api/src/main.ts b/packages/leaa-api/src/main.ts index c6e1d642..229fd43e 100644 --- a/packages/leaa-api/src/main.ts +++ b/packages/leaa-api/src/main.ts @@ -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, }); diff --git a/packages/leaa-dashboard/package.json b/packages/leaa-dashboard/package.json index 52e4f80e..02d642e0 100644 --- a/packages/leaa-dashboard/package.json +++ b/packages/leaa-dashboard/package.json @@ -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": { diff --git a/packages/leaa-dashboard/src/interfaces/http.interface.ts b/packages/leaa-dashboard/src/interfaces/http.interface.ts index bdcf58d4..e28eec0a 100644 --- a/packages/leaa-dashboard/src/interfaces/http.interface.ts +++ b/packages/leaa-dashboard/src/interfaces/http.interface.ts @@ -12,4 +12,8 @@ export interface IHttpRes extends AxiosResponse { }; } +export interface IFetchRes extends AxiosResponse { + data: T; +} + export interface IHttpError extends AxiosError {} diff --git a/packages/leaa-dashboard/src/libs/fetcher.lib.ts b/packages/leaa-dashboard/src/libs/fetcher.lib.ts new file mode 100644 index 00000000..4989ad24 --- /dev/null +++ b/packages/leaa-dashboard/src/libs/fetcher.lib.ts @@ -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.'); +}; diff --git a/packages/leaa-dashboard/src/libs/index.ts b/packages/leaa-dashboard/src/libs/index.ts index 70a59d1a..8316c4f3 100644 --- a/packages/leaa-dashboard/src/libs/index.ts +++ b/packages/leaa-dashboard/src/libs/index.ts @@ -1 +1,3 @@ export * from './history.lib'; +export * from './fetcher.lib'; +export * from './use-fetch.lib'; diff --git a/packages/leaa-dashboard/src/libs/use-fetch.lib.ts b/packages/leaa-dashboard/src/libs/use-fetch.lib.ts new file mode 100644 index 00000000..17614ae4 --- /dev/null +++ b/packages/leaa-dashboard/src/libs/use-fetch.lib.ts @@ -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 extends AxiosResponse { + config: IAxiosRequestConfig; +} + +interface IReturn + extends Pick< + responseInterface, AxiosError>, + 'isValidating' | 'revalidate' | 'error' | 'mutate' + > { + data: Data | undefined; + loading?: boolean; + response?: IAxiosResponse | undefined; +} + +export interface IConfig + extends Omit, AxiosError>, 'initialData'> { + initialData?: Data; +} + +export function useFetch( + request: IAxiosRequestConfig | null, + { initialData, ...config }: IConfig = {}, +): IReturn { + const { data: response, error, isValidating, revalidate, mutate } = useSWR, AxiosError>( + 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, + }; +} diff --git a/packages/leaa-dashboard/src/pages/Attachment/AttachmentList/AttachmentList.tsx b/packages/leaa-dashboard/src/pages/Attachment/AttachmentList/AttachmentList.tsx index 4b9ebdab..c91c66c5 100644 --- a/packages/leaa-dashboard/src/pages/Attachment/AttachmentList/AttachmentList.tsx +++ b/packages/leaa-dashboard/src/pages/Attachment/AttachmentList/AttachmentList.tsx @@ -1,16 +1,15 @@ 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, @@ -18,6 +17,7 @@ import { 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'; @@ -28,30 +28,27 @@ export default (props: IPage) => { const [crudQuery, setCrudQuery] = useState({ ...DEFAULT_QUERY, - ...transUrlQueryToCrudState(window), sort: ['created_at', 'DESC'], + ...transUrlQueryToCrudState(window), }); - const [list, setList] = useState>(); - 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>) => { - 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>>( + { + 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 ( { /> } className={style['wapper']} - loading={listLoading} + loading={list.loading} > - {list?.data && ( + {list.data?.data && ( { 'status', { action: { fieldName: 'title' } }, ]} - list={list} + list={list.data?.data} /> )} diff --git a/packages/leaa-dashboard/src/pages/Tag/TagEdit/TagEdit.tsx b/packages/leaa-dashboard/src/pages/Tag/TagEdit/TagEdit.tsx index 2c07d4de..0ab93edb 100644 --- a/packages/leaa-dashboard/src/pages/Tag/TagEdit/TagEdit.tsx +++ b/packages/leaa-dashboard/src/pages/Tag/TagEdit/TagEdit.tsx @@ -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'; @@ -20,38 +21,28 @@ export default (props: IPage) => { const { id } = props.match.params as { id: string }; const infoFormRef = useRef>(null); - - const [item, setItem] = useState(); - 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) => { - setItem(res.data.data); - }) - .catch((err: IHttpError) => errorMsg(err.response?.data?.message || err.message)) - .finally(() => setItemLoading(false)); - }; + const item = useFetch>( + { 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 = await infoFormRef.current?.onValidateForm(); if (!infoData) return; - const data: ISubmitData = { - ...infoData, - }; - + const data: ISubmitData = { ...infoData }; setSubmitLoading(true); - ajax + fetcher .patch(`${envConfig.API_URL}/${envConfig.API_VERSION}/${API_PATH}/${id}`, data) - .then((res: IHttpRes) => { - setItem(res.data.data); + .then((res: IFetchRes) => { + item.mutate(res, false); msg(t('_lang:updatedSuccessfully')); }) @@ -59,14 +50,11 @@ export default (props: IPage) => { .finally(() => setSubmitLoading(false)); }; - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(() => onFetchItem(), []); - return ( - + - + { ...transUrlQueryToCrudState(window), }); - const [listLoading, setListLoading] = useState(false); - - const [list, setList] = useState>(); - - const onFetchList = (params: ICrudListQueryParams) => { - setCrudQuery(params); - setListLoading(true); - - ajax - .get(`${envConfig.API_URL}/${envConfig.API_VERSION}/${API_PATH}`, { params: genCrudRequestQuery(params) }) - .then((res: IHttpRes>) => { - 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>>( + { + 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 ( { /> } className={style['wapper']} - loading={listLoading} + loading={list.loading} > - {list?.data && ( - - )} +
diff --git a/packages/leaa-dashboard/src/pages/TestWithoutLayout/TestAnyWithoutLayout/TestAnyWithoutLayout.tsx b/packages/leaa-dashboard/src/pages/TestWithoutLayout/TestAnyWithoutLayout/TestAnyWithoutLayout.tsx index 89c97787..ffbf10cd 100644 --- a/packages/leaa-dashboard/src/pages/TestWithoutLayout/TestAnyWithoutLayout/TestAnyWithoutLayout.tsx +++ b/packages/leaa-dashboard/src/pages/TestWithoutLayout/TestAnyWithoutLayout/TestAnyWithoutLayout.tsx @@ -2,10 +2,21 @@ import React from 'react'; import { IPage } from '@leaa/dashboard/src/interfaces'; import { RiMenuLine, RiCheckboxCircleLine } from 'react-icons/ri'; import { FiCheckCircle } from 'react-icons/fi'; +import { useFetch } from '@leaa/dashboard/src/libs'; +import { envConfig } from '@leaa/dashboard/src/configs'; import { CrudRequestTest as Test } from './_components/CrudRequestTest/CrudRequestTest'; +const API_PATH = 'attachments'; + export default (props: IPage) => { + const { data, loading: aa } = useFetch({ + // url: '/api/data', + url: `${envConfig.API_URL}/${envConfig.API_VERSION}/${API_PATH}`, + }); + + console.log(aa, data); + return (
diff --git a/yarn.lock b/yarn.lock index 97c2c9f5..5e103d8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8215,6 +8215,11 @@ extsprintf@^1.2.0: resolved "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= +fast-deep-equal@2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz?cache=0&sync_timestamp=1591599697571&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-deep-equal%2Fdownload%2Ffast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -16759,6 +16764,13 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" +swr@^0.2.3: + version "0.2.3" + resolved "https://registry.npm.taobao.org/swr/download/swr-0.2.3.tgz#e0fb260d27f12fafa2388312083368f45127480d" + integrity sha1-4PsmDSfxL6+iOIMSCDNo9FEnSA0= + dependencies: + fast-deep-equal "2.0.1" + symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.npm.taobao.org/symbol-observable/download/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"