最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

React-Query:解鎖你的應(yīng)用程序潛力,輕松解決接口請(qǐng)求難題!

2023-10-03 09:46 作者:塵緣如夢(mèng)_  | 我要投稿
{"ops":[{"insert":"前言"},{"attributes":{"header":2},"insert":"\n"},{"insert":"如果你平常會(huì)寫(xiě)前后端交互的react頁(yè)面,那你一定寫(xiě)過(guò)這樣的代碼.\n?function App() {\n??\n??const [data, updateData] = useState(null);\n??const [isError, setError] = useState(false);\n??const [isLoading, setLoading] = useState(false);\n??\n??useEffect(async () => {\n???setError(false);\n???setLoading(true);\n???try {\n????const data = await axios.get('/api/user');\n????updateData(data);\n??} catch(e) {\n????setError(true);\n??}\n???setLoading(false);\n? }, [])\n??\n??if(isLoading) return ...\n??\n??if(isError) return ...\n??\n??return \n?}\n??\n這是一個(gè)組件拉取服務(wù)端數(shù)據(jù)的簡(jiǎn)單例子,在組件中,我們簡(jiǎn)單拉取了一個(gè)接口的數(shù)據(jù),并監(jiān)聽(tīng)接口的狀態(tài),根據(jù)狀態(tài)來(lái)更新不同的UI。\n如果有性能上的要求,那這里可能還需要加上一段緩存的邏輯\n?//...\n???try {\n?+???if(sessionUtil.get('users'){\n?+?????updateData(sessionUtil.get('users'));\n?+?????return;\n?+??}\n????const data = await axios.get('/api/user');\n?+??sessionUtil.set('users',data)\n????updateData(data);\n??} catch(e) {\n????setError(true);\n??}\n?//...\n至此,這個(gè)組件已經(jīng)變得相當(dāng)復(fù)雜了,如果組件拉取了好幾個(gè)接口,那么這一套邏輯還得寫(xiě)好幾遍。\n1 一些狀態(tài)管理庫(kù)的弊端"},{"attributes":{"header":2},"insert":"\n"},{"insert":"許多狀態(tài)管理庫(kù),比如redux,可以很流暢的管理頁(yè)面的狀態(tài),也有處理副作用的能力,但往往不能很好的處理服務(wù)端的狀態(tài),因?yàn)樘幚矸?wù)端的狀態(tài),通常還包括:\n緩存"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"將對(duì)同一數(shù)據(jù)的多個(gè)請(qǐng)求消除為一個(gè)請(qǐng)求"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"在后臺(tái)更新“過(guò)期”數(shù)據(jù)"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"知道數(shù)據(jù)何時(shí)“過(guò)期”"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"盡快反映數(shù)據(jù)更新"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"性能優(yōu)化,如分頁(yè)和延遲加載數(shù)據(jù)"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"管理內(nèi)存和服務(wù)器狀態(tài)的垃圾收集"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"使用結(jié)構(gòu)共享記憶查詢(xún)結(jié)果"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"直到React-Query的出現(xiàn),上面的問(wèn)題都變得迎刃而解。\n2 React-Query"},{"attributes":{"header":2},"insert":"\n"},{"insert":"React Query 是一個(gè)開(kāi)箱即用,零配置的服務(wù)端狀態(tài)管理庫(kù),支持Restful和GraphQL兩種類(lèi)型的請(qǐng)求,它能幫助你很好的獲取、同步、管理和緩存你的遠(yuǎn)程數(shù)據(jù)。它提供了幾個(gè)簡(jiǎn)單的Hooks,借助它們可以很輕松的完成對(duì)后端數(shù)據(jù)的增刪改查等操作,無(wú)需再寫(xiě)繁瑣的數(shù)據(jù)拉取和狀態(tài)判斷等代碼。\nReact-Query的官方文檔沒(méi)有大綱,閱讀起來(lái)相當(dāng)不方便,個(gè)人感覺(jué),直接閱讀github源碼項(xiàng)目中的docs要更方便一些。鏈接地址:"},{"attributes":{"bold":true},"insert":"https://github.com/TanStack/query/tree/main/docs/react"},{"attributes":{"blockquote":true},"insert":"\n"},{"insert":"2.1 簡(jiǎn)單使用\n2.1.1 QueryClientProvider\n首先,需要在組件外層定義一個(gè)queryClient作為組件操作和使用數(shù)據(jù)的一個(gè)共同容器,通過(guò)QueryClientProvider組件注入到項(xiàng)目中。\n?import {\n??QueryClient,\n??QueryClientProvider,\n??useQuery,\n?} from '@tanstack/react-query'\n??\n?const queryClient = new QueryClient()\n??\n?export default function App() {\n??return (\n???\n????\n???\n? )\n?}\n在創(chuàng)建QueryClient的時(shí)候,我們可以傳入一些參數(shù),用于管理項(xiàng)目中的請(qǐng)求、緩存、日志的相關(guān)配置,這些配置會(huì)對(duì)整個(gè)項(xiàng)目生效,其中包含了四個(gè)模塊的配置參數(shù)。\n?new QueryClient({\n??queryCache?: QueryCache;\n??mutationCache?: MutationCache;\n??logger?: Logger;\n??defaultOptions?: DefaultOptions;\n?})\nqueryCache: 請(qǐng)求緩存相關(guān)配置"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"mutationCache: 數(shù)據(jù)修改緩存相關(guān)配置"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"logger: 日志相關(guān)配置 "},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"defaultOptions:請(qǐng)求基礎(chǔ)配置"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"其中defaultOptions用于配置項(xiàng)目中useQuery請(qǐng)求的管理,常用的配置如下:\nstaleTime: 重新獲取數(shù)據(jù)的時(shí)間間隔 默認(rèn)0"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"cacheTime: 數(shù)據(jù)緩存時(shí)間 默認(rèn) 1000 60 5 5分鐘"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"retry: 失敗重試次數(shù) 默認(rèn) 3次"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"refetchOnWindowFocus: 窗口重新獲得焦點(diǎn)時(shí)重新獲取數(shù)據(jù) 默認(rèn) false"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"refetchOnReconnect: 網(wǎng)絡(luò)重新鏈接"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"refetchOnMount: 實(shí)例重新掛載時(shí)重新拉取請(qǐng)求"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"enabled: 如果為“false”,“useQuery”不會(huì)觸發(fā),需要使用其返回的“refetch”來(lái)觸發(fā)操作"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"queryFn:全局定義請(qǐng)求方法,其他地方使用時(shí)只需要直接傳入請(qǐng)求參數(shù)"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"2.1.2 useQuery\nuseQuery是React-Query提供的用于請(qǐng)求接口并管理請(qǐng)求狀態(tài)等信息的Hook。\n例如:\n?function Example() {\n??const { isLoading, error, data } = useQuery({\n???queryKey: ['repoData'],\n???queryFn: () =>\n????fetch('https://api.github.com/repos/TanStack/query').then(\n????(res) => res.json(),\n???),\n? })\n??\n??if (isLoading) return 'Loading...'\n??\n??if (error) return 'An error has occurred: ' + error.message\n??\n??return (\n???
\n????

{data.name}

\n????

{data.description}

\n?????? {data.subscribers_count}{' '}\n????? {data.stargazers_count}{' '}\n?????? {data.forks_count}\n???
\n? )\n?}\nuserQuery接收一個(gè)配置對(duì)象,其中\(zhòng)nqueryKey:必傳,用作請(qǐng)求數(shù)據(jù)緩存的唯一key值,也可以在數(shù)組中,寫(xiě)入多項(xiàng)如:['repoData', '1'],這樣React-Query在使用的時(shí)候會(huì)自動(dòng)把它拼接為/repoData/1,這個(gè)在緩存用戶(hù)訪問(wèn)過(guò)的頁(yè)面時(shí),非常有用。"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"queryFn:用于請(qǐng)求的方法,如果在QueryClient中配置了,這里可以不必再寫(xiě),需要返回請(qǐng)求完成后所處理的數(shù)據(jù)。"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"除了這兩項(xiàng)基本的參數(shù),useQuery還可以傳入上面defaultOptions的所有參數(shù),來(lái)表示對(duì)這個(gè)請(qǐng)求單獨(dú)的配置。\n然后useQuery會(huì)返回一個(gè)對(duì)象,里面包含著請(qǐng)求相關(guān)的所有信息,這些信息會(huì)隨著請(qǐng)求的進(jìn)度而改變,就無(wú)須我們?cè)偈褂靡唤Mstate變量來(lái)進(jìn)行管理了,常用的包括:\nisLoading:請(qǐng)求是否正在進(jìn)行"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"error:請(qǐng)求是否出錯(cuò),這里只會(huì)對(duì)500,404等做出反應(yīng),如果有其他情況錯(cuò)誤情況,需要在請(qǐng)求方法里面throw"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"isSuccess: 請(qǐng)求是否成功"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"status: 請(qǐng)求狀態(tài),包含上面幾種情況"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"data:返回?cái)?shù)據(jù)"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"除此之外,使用useQuery拉取回來(lái)的數(shù)據(jù),會(huì)被默認(rèn)緩存起來(lái),然后可以通過(guò)配置過(guò)期時(shí)間,重新拉取等策略來(lái)進(jìn)行管理。\n2.1.3 useQueryClient\n通過(guò)useQueryClient,我們可以獲取到之前注入的容器實(shí)例,里面保存著所有我們緩存的信息,以及配置信息,而它本質(zhì)上其實(shí)也是對(duì)React.useContext的封裝。\n以上面Example組件為例,如果我們想在另一個(gè)組件訪問(wèn)這些數(shù)據(jù)。\n?function Example() {\n??const queryClient = useQueryClient()\n??\n??const data = queryClient.getQueryData(['repoData'])\n??\n??return (\n???//...\n? )\n?}\n除了訪問(wèn)緩存數(shù)據(jù),queryClient還有很多API:\n"},{"attributes":{"bold":true},"insert":"queryClient.fetchQuery"},{"attributes":{"list":"bullet"},"insert":"\n"},{"attributes":{"bold":true},"insert":"queryClient.fetchInfiniteQuery"},{"attributes":{"list":"bullet"},"insert":"\n"},{"attributes":{"bold":true},"insert":"queryClient.prefetchQuery"},{"attributes":{"list":"bullet"},"insert":"\n"},{"attributes":{"bold":true},"insert":"queryClient.prefetchInfiniteQuery"},{"attributes":{"list":"bullet"},"insert":"\n"},{"attributes":{"bold":true},"insert":"queryClient.getQueryData"},{"attributes":{"list":"bullet"},"insert":"\n"},{"attributes":{"bold":true},"insert":"queryClient.refetchQueries"},{"attributes":{"list":"bullet"},"insert":"\n"},{"attributes":{"bold":true},"insert":"queryClient.cancelQueries"},{"attributes":{"list":"bullet"},"insert":"\n"},{"attributes":{"bold":true},"insert":"queryClient.removeQueries"},{"attributes":{"list":"bullet"},"insert":"\n"},{"attributes":{"bold":true},"insert":"queryClient.resetQueries"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"..."},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"大家可以根據(jù)需要去官網(wǎng)查閱。\n2.1.4 useMutation\n除了獲取數(shù)據(jù),很多時(shí)候還需要處理數(shù)據(jù)的修改,比如說(shuō)最簡(jiǎn)單的todo list例子,除了拉取數(shù)據(jù)列表,還需要增刪改數(shù)據(jù),而這個(gè)時(shí)候除了需要發(fā)送接口,還需要修改本地的數(shù)據(jù),React-Query提供了useMutation來(lái)幫我們完成這些事情。\n以上面Example組件為例,我們已經(jīng)拉取到了data,現(xiàn)在我們想新增一條數(shù)據(jù),那我們可以\n?const {isLoading,isError,isSuccess,mutate} = useMutation({\n???mutationFn: async (newData) => insertNewData(newData),\n???onSuccess: () => {\n????queryClient.invalidateQueries({ queryKey: ['repoData'] });\n??},\n???onError: (error) => {\n????console.log(error)\n??}\n? });\n這里我們傳入了:\nmutationFn:代表元數(shù)據(jù)的方法"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"onSuccess:接口調(diào)用成功后的回調(diào)"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"onError: 失敗的回調(diào)"},{"attributes":{"list":"bullet"},"insert":"\n"},{"insert":"返回的數(shù)據(jù)和useQuery基本是相同的,這里的mutate則是觸發(fā)更改的方法,如果我們想執(zhí)行useMutation中傳入的方法,我們只需要調(diào)用mutate即可,傳給mutate的參數(shù)都會(huì)被帶到useMutation的構(gòu)造方法中。\n??const updateData = async (newData) => {\n???mutate(newData);\n? };\n\n\n以上就是React-Query最核心的對(duì)服務(wù)端數(shù)據(jù)進(jìn)行增刪改查的功能,除此之外,React-Query還有很多其他的能力。\n2.2 數(shù)據(jù)預(yù)獲取\n有時(shí)候我們不需要整個(gè)頁(yè)面loading來(lái)等待數(shù)據(jù)加載,我們更希望在用戶(hù)操作之前就拉取完數(shù)據(jù),比如用戶(hù)hover詳情鏈接,而不是點(diǎn)擊詳情的時(shí)候。\n那我們可以使用queryClient的prefetchQuery方法,提前拉取到用戶(hù)可能會(huì)訪問(wèn)的數(shù)據(jù),并加入到緩存中,由于不需要監(jiān)聽(tīng)服務(wù)端狀態(tài)等,所以這個(gè)方法會(huì)比useQuery高效許多。\nonMouseEnter={async () => {\n await queryClient.prefetchQuery({\n queryKey: ['character', char.id],\n queryFn: () => getCharacter(char.id),\n staleTime: 10 * 1000, // only prefetch if older than 10 seconds\n })\n}}\n2.3 分頁(yè)緩存\n通過(guò)動(dòng)態(tài)設(shè)置queryKey,并將keepPreviousData設(shè)置為true,我們可以很輕松的緩存之前頁(yè)碼的數(shù)據(jù)\n const { status, data, error, isFetching, isPreviousData } = useQuery({\n queryKey: ['projects', page],\n queryFn: () => fetchProjects(page),\n keepPreviousData: true,\n staleTime: 5000,\n })\n2.4 滾動(dòng)列表渲染\n使用useInfiniteQuery定義拉取數(shù)據(jù)的方法,以及上下頁(yè)的邏輯,然后會(huì)返回更新頁(yè)面數(shù)據(jù)的狀態(tài),以及觸發(fā)更新的方法。\n const {\n status,\n data,\n error,\n isFetching,\n isFetchingNextPage,\n isFetchingPreviousPage,\n fetchNextPage,\n fetchPreviousPage,\n hasNextPage,\n hasPreviousPage,\n } = useInfiniteQuery(\n ['projects'],\n async ({ pageParam = 0 }) => {\n const res = await axios.get('/api/projects?cursor=' + pageParam)\n return res.data\n },\n {\n getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined,\n getNextPageParam: (lastPage) => lastPage.nextId ?? undefined,\n },\n )\n2.5 devTools配套開(kāi)發(fā)工具\(yùn)n導(dǎo)入開(kāi)發(fā)工具\(yùn)nimport { ReactQueryDevtools } from 'react-query/devtools'\n\n\n默認(rèn)情況下,當(dāng)process.env.NODE ENV === 'production' 時(shí)開(kāi)啟 Devtools ,不必?fù)?dān)心構(gòu)建時(shí)需要排除他們\n浮動(dòng)模式下開(kāi)啟,會(huì)將devtools作為固定的浮動(dòng)元素安裝在開(kāi)發(fā)的應(yīng)用程序中,并在屏幕一角提供一個(gè)切換按鈕以顯示和隱藏devtools\n在devtools中我們可以直觀的看到已經(jīng)緩存下來(lái)的數(shù)據(jù)和整個(gè)項(xiàng)目的配置,以及各個(gè)接口的狀態(tài)等。\n\n3 總結(jié)"},{"attributes":{"header":2},"insert":"\n"},{"insert":"感謝你能看到這里,本文簡(jiǎn)單介紹了React-Query對(duì)服務(wù)端數(shù)據(jù)進(jìn)行增刪改查的功能實(shí)現(xiàn),以及React-Query的一些其他能力,希望對(duì)你有用,React-Query的使用場(chǎng)景沒(méi)有其他狀態(tài)管理庫(kù)那么廣泛,但還是能解決很多服務(wù)器拉取數(shù)據(jù)的痛點(diǎn)。\n"}]}

React-Query:解鎖你的應(yīng)用程序潛力,輕松解決接口請(qǐng)求難題!的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
澄城县| 固安县| 乐至县| 循化| 丰镇市| 康保县| 昭通市| 株洲市| 乐亭县| 淮阳县| 金湖县| 陇西县| 金溪县| 科尔| 和田市| 顺义区| 开江县| 璧山县| 拉孜县| 琼结县| 永嘉县| 襄樊市| 黔西县| 连州市| 深泽县| 太原市| 洪江市| 哈尔滨市| 内乡县| 和平县| 福鼎市| 汝州市| 汉寿县| 夏邑县| 富锦市| 丹寨县| 美姑县| 龙里县| 神木县| 岚皋县| 闽侯县|